/**
 * @file comms_sband_rssi_hdlr.c
 *
 * @brief This file has the S-Band driver thread functions and other main functions for S-Band control
 *
 * @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 "sdr_app_main.h"
#include "exo_common.h"
#include "comms_csw.h"
#include "comms_ipc.h"
#include "comms_sband_xlink_ss.h"
#include "comms_sband_xlink_api.h"
#include "comms_sband_intf.h"
#include "math.h"
#include "comms_sband_xlink_api.h"
#include "comms_sband_xlink_sock.h"
#include "exo_io_al_rtc_common.h"
#include "exo_io_al_sos_timer.h"
#include "exo_tctm_ipc.h"
#include "logger.h"
#include "eps_ctrlr.h"
#include "exo_osal_common.h"
#include "err_handler.h"

/** Time struct for RSSI handler */
sys_time_date_s tim_get_rs_hlr;

/** Minimum S-band TM read period macro */  
#define MIN_SBAND_TM_READ_PRD 30*1000
/** Maximum RSSI storage size macro */
#define MAX_RSSI_STORE 32

extern uint8_t sband_iqs_tx_ON;
/** External - S-band RSSI configuration struct */
extern s_sdr_rssi_cfg PLACE_IN_EXT_RAM_MEM sband_rssi_cfg;

/** External - S-band timer configuration struct */
extern s_sdr_tmr_cfg PLACE_IN_EXT_RAM_MEM sband_tmr_cfg;
/** External - S-band service device configuration struct */ 
extern SERVICE_DEVICE_CONF_STRUCT   PLACE_IN_EXT_RAM_MEM sband_serv_device_conf;
extern SERVICE_START_RF_RCV_STRUCT  PLACE_IN_EXT_RAM_MEM   sband_serv_start_rf_rcv;
/** Timer used for RX on Timer */
extern os_timer_handle_ptr sband_rx_on_timer;
/** Timer used for periodic TM read */
extern os_timer_handle_ptr sband_tm_periodic_read;
/** Timer used for S-band re-initialization */
extern os_timer_handle_ptr sband_reinit_tmr;

/** External - S-band service housekeeping struct */
extern SERVICE_HOUSE_KEEP_STRUCT PLACE_IN_EXT_RAM_MEM       sband_serv_house_keep;

/** External - S-band sensitivity config struct */
extern s_sdr_sens_cfg PLACE_IN_EXT_RAM_MEM sband_sens_cfg;
/** External - Housekeeping update ID variable */
extern uint8_t s_comms_hk_upd_id;
/** External - Housekeeping update ID fill flag */
extern uint8_t is_comms_hk_upd_id_fill;

/** Current receiver variable */
uint8_t PLACE_IN_EXT_RAM_MEM curr_rx = 0;

/** Receiver sync state variable */  
uint32_t PLACE_IN_EXT_RAM_MEM rx_sync_state = 0;
/** RSSI storage array */
float rx_rssi[MAX_RX_CH][MAX_RSSI_STORE] = {{0}};
/** RSSI index array */
uint32_t rssi_idx[MAX_RX_CH] = {0};
/** Valid RSSI count array */
uint32_t PLACE_IN_EXT_RAM_MEM valid_rssi[MAX_RX_CH] = {0};
/** Invalid RSSI count array */
uint32_t PLACE_IN_EXT_RAM_MEM inv_rssi[MAX_RX_CH] = {0};
/** Average RSSI valid flag array */
uint8_t PLACE_IN_EXT_RAM_MEM  avg_rssi_valid[MAX_RX_CH] = {0};
/** Average RSSI array */
float PLACE_IN_EXT_RAM_MEM avg_rssi[MAX_RX_CH] = {0};

/** Receiver sync array */
uint8_t PLACE_IN_EXT_RAM_MEM rx_sync[MAX_RX_CH] = {0};
/** TM storage count */
uint32_t PLACE_IN_EXT_RAM_MEM tm_store_cnt = 0;
/** TM read count variable */
uint32_t PLACE_IN_EXT_RAM_MEM tm_read_cnt = 0;
/** RSSI logic enable variable */
uint8_t PLACE_IN_EXT_RAM_MEM rssi_logic_en = 1;
uint8_t xlinks_rx_ch_en[2] = {0};

/**
 * @brief S-band RSSI event handler. 
 *
 * This function handles the RSSI event by reading current RSSI 
 * values and updating housekeeping parameters.
 *
 * @param event_id Event ID
*/
void comms_sband_rssi_hdlr(uint16_t event_id)
{
    uint8_t status = 0;

    status = status;
    DEBUG_CPRINT(("The EVNT_ID is %d", event_id ));
    log_id_with_one_arg(LOG_INFO_L2,LOG_COMMS,EVENT_ID__u8_,event_id);

    switch(event_id)
    {
        case OBC_SBAND_INIT_REQ:
            {
#ifdef COMMS_TIME_DEBUG 
                get_crnt_time_date(&tim_get_rs_hlr);
                comms_sband_reset_rssi_proc();
                DEBUG_CPRINT(("\nSBAND TIME S_RX_ON TMR ENT %d:%d:%d - RX_ON_TMR %d",tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds, sband_rssi_cfg.short_rx_on_tmr));
                log_id_with_four_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TMIE_S_RX_ON_TMR_ENT_u8__u8__u8__RX_ON_TMR__u32_,tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds, sband_rssi_cfg.short_rx_on_tmr);
#endif

                DEBUG_CPRINT(("\nRSSI_PRD_TMR:%d\n",sband_rssi_cfg.rssi_prd_tmr));
                /** TM Periodic read timer ON**/
                if((sband_tmr_cfg.sdr_tm_read_tmr >= sband_rssi_cfg.rssi_prd_tmr)&&(sband_rssi_cfg.rssi_prd_tmr !=0))
                {
                    tm_store_cnt = sband_tmr_cfg.sdr_tm_read_tmr/sband_rssi_cfg.rssi_prd_tmr;
                    os_timer_start(sband_tm_periodic_read, sband_rssi_cfg.rssi_prd_tmr);
                }
                else
                {
                    tm_store_cnt = 1;
                    os_timer_start(sband_tm_periodic_read, sband_tmr_cfg.sdr_tm_read_tmr);
                }

                s_comms_hk_upd_id = 0;
                is_comms_hk_upd_id_fill = 0;

                /** RX_short timer ON **/
                os_timer_start(sband_rx_on_timer, sband_rssi_cfg.short_rx_on_tmr);
            }
            break;

        case OBC_SBAND_DEINIT_REQ:
            {
                /** RX _short timer OFF **/
                os_timer_stop(sband_rx_on_timer); //TODO TX & RX ch 1& 2stop
#ifdef COMMS_TIME_DEBUG 
                get_crnt_time_date(&tim_get_rs_hlr);
                DEBUG_CPRINT(("\nSBAND TIME RX_ON TMR_STP %d:%d:%d",tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds));
                log_id_with_three_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_RX_ON_TMR_STP__u8__u8__u8_,tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds);
#endif

                s_comms_hk_upd_id = 0;
                is_comms_hk_upd_id_fill = 0;
                os_timer_stop(sband_tm_periodic_read);
#ifdef COMMS_TIME_DEBUG
                get_crnt_time_date(&tim_get_rs_hlr);
                DEBUG_CPRINT(("\nSBAND TIME TM_RD TMR_STP %d:%d:%d",tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds));
                log_id_with_three_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_TM_RD_TMR_STP__u8__u8__u8_,tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds);
#endif

                /**Timer stop for all beacon**/
            }
            break;

        case SBAND_RX_ON_TIMER_EXP:
            {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
                DEBUG_CPRINT(("The READ_CNT at RX_ON TIMER EXP %ld \n",tm_read_cnt ));
                log_id_with_one_arg(LOG_INFO_L1,LOG_COMMS,READ_CNT_AT_RX_ON_TIMER_EXP__u32_,tm_read_cnt);
#pragma GCC diagnostic pop

                comms_sband_rx_switch();
            }
            break;

        case SBAND_TM_PERIODIC_READ:
            {
                DEBUG_CPRINT(("\nSBAND TIME TM_RD TMR EXP "));

                status = sband_proc_tc(SERVICE_GET | SERVICE_HOUSE_KEEP);

                log_id(LOG_INFO_L1,LOG_COMMS,SBAND_TIME_TM_RD_TMR_EXP);

                if(!status)
                {
                    tm_read_cnt ++;

                    sband_xlinks_health_check();

                    if(tm_read_cnt == tm_store_cnt)
                    {
                        tm_read_cnt = 0;
                        sband_xlinks_health_report_tm();
                    }
                }

                if(rssi_logic_en)
                {
                    if(!status)
                    {
                        comms_sband_rx_switch();
                    }

                    if(sband_tmr_cfg.sdr_tm_read_tmr >= sband_rssi_cfg.rssi_prd_tmr)
                    {
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"

                        DEBUG_CPRINT(("\nRSSI_RD_CNT at TM_READ TIMER ENT %lu \n",tm_read_cnt));
                        log_id_with_one_arg(LOG_INFO_L1,LOG_COMMS,RSSI_RD_CNT_AT_TM_READ_ENT__u32_,tm_read_cnt);
#pragma GCC diagnostic pop

                        DEBUG_CPRINT(("\nsband rssi_prd_timer %d \n", sband_rssi_cfg.rssi_prd_tmr));
                        log_id_with_one_arg(LOG_INFO_L1,LOG_COMMS,SBAND_RSSI_PRD_TIMER__u32_,sband_rssi_cfg.rssi_prd_tmr);

                        if(sband_rssi_cfg.rssi_prd_tmr < MIN_SBAND_TM_READ_PRD)
                        {
                            tm_store_cnt = sband_tmr_cfg.sdr_tm_read_tmr/sband_rssi_cfg.rssi_prd_tmr;

                            os_timer_start(sband_tm_periodic_read, sband_rssi_cfg.rssi_prd_tmr);
                        }
                        else
                        {
                            tm_store_cnt = sband_tmr_cfg.sdr_tm_read_tmr/MIN_SBAND_TM_READ_PRD;

                            os_timer_start(sband_tm_periodic_read,MIN_SBAND_TM_READ_PRD);
                        }

                    }
                    else
                    {
                        //  DEBUG_CPRINT(("The TIMER START at TM_READ TIMER EXP ELSE %lu \n",tm_read_cnt ));
                        tm_store_cnt = 1;
                        os_timer_start(sband_tm_periodic_read, sband_tmr_cfg.sdr_tm_read_tmr);
                    }
#ifdef COMMS_TIME_DEBUG
                    get_crnt_time_date(&tim_get_rs_hlr);
                    DEBUG_CPRINT(("\nSBAND TIME TM_RD TMR ENT %d:%d:%d",tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds));
                    log_id_with_three_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_TM_RD_TMR_ENT__u8__u8__u8_,tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds);
#endif 
                }
                else
                {
                    if(sband_tmr_cfg.sdr_tm_read_tmr < MIN_SBAND_TM_READ_PRD)
                    {
                        tm_store_cnt = 1;
                        os_timer_start(sband_tm_periodic_read, sband_tmr_cfg.sdr_tm_read_tmr);
                    }
                    else
                    {
                        tm_store_cnt = sband_tmr_cfg.sdr_tm_read_tmr/MIN_SBAND_TM_READ_PRD;
                        os_timer_start(sband_tm_periodic_read,MIN_SBAND_TM_READ_PRD);
                    }
                }
            }
            break;
    }
}

/**
 * @brief Get average S-band RSSI value.
 *
 * This function returns the average RSSI value for the 
 * given S-band receiver.
 * 
 * @param rx S-band receiver ID
 * @return Average RSSI value (dBm)
*/
float comms_sband_get_avg_rssi(uint8_t rx)
{
    uint32_t rssi_i = 0;
    float avg_rssi = 0;

    float rssi_linear_sum = 0;

    float rssi_val =0;

    for (rssi_i = 0; rssi_i < sband_rssi_cfg.valid_rssi_cnt; rssi_i++)
    {
        rssi_val = rx_rssi[rx][rssi_i];
        rssi_linear_sum += powf(10, (float)rssi_val / 20);
    }
    avg_rssi = 20 * log10f(rssi_linear_sum / sband_rssi_cfg.valid_rssi_cnt);

    DEBUG_CPRINT(("AVERAGE_RSSI: %f \n",rssi_linear_sum ));
    log_id_with_float(LOG_INFO_L2,LOG_COMMS,RSSI_LINEAR_SUM__u32_,rssi_linear_sum);

    DEBUG_CPRINT(("AVERAGE_RSSI: %f \n",avg_rssi ));
    log_id_with_float(LOG_INFO_L2,LOG_COMMS,AVERAGE_RSSI__u32_,avg_rssi);
    return avg_rssi;
}

/**
 * @brief Switch S-band receiver.
 *
 * This function switches between main and backup
 * S-band receivers.
 *
 * @return Status of receiver switch operation.
*/
int8_t comms_sband_rx_switch(void)
{
    DEBUG_CPRINT(("\nSBAND TIME TM_RD_RX_ST_1"));
    log_id(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_TM_RD_RX_ST_1);
    rx_sync[RX_CH_0] = comms_sband_rx_get_sync_state(RX_CH_0);
    rx_sync[RX_CH_1] = comms_sband_rx_get_sync_state(RX_CH_1);
    DEBUG_CPRINT(("curr_rx %d\n", curr_rx));
    log_id_with_one_arg(LOG_INFO_L2,LOG_COMMS,CURRENT_RX__u8_,curr_rx);
    rx_rssi[RX_CH_0][rssi_idx[RX_CH_0]] = comms_xlink_s_get_rssi(RX_CH_0);
    rx_rssi[RX_CH_1][rssi_idx[RX_CH_1]] = comms_xlink_s_get_rssi(RX_CH_1);

    DEBUG_CPRINT(("rx_rssi_0 %f\n", rx_rssi[RX_CH_0][rssi_idx[RX_CH_0]]));
    log_id_with_float(LOG_INFO_L2,LOG_COMMS,RX_RSSI_0__u32_,curr_rx);
    DEBUG_CPRINT(("rx_rssi_1 %f\n", rx_rssi[RX_CH_1][rssi_idx[RX_CH_1]]));
    log_id_with_float(LOG_INFO_L2,LOG_COMMS,RX_RSSI_1__u32_,curr_rx);
    DEBUG_CPRINT(("rx_sync_0 %d\n", rx_sync[RX_CH_0]));
    log_id_with_float(LOG_INFO_L2,LOG_COMMS,RX_SYNC_0__u32_,curr_rx);
    DEBUG_CPRINT(("rx_sync_1 %d\n", rx_sync[RX_CH_1]));
    log_id_with_float(LOG_INFO_L2,LOG_COMMS,RX_SYNC_1__u32_,curr_rx);

    if(rx_sync[RX_CH_0] || rx_sync[RX_CH_1])
    {
        curr_rx = ((rx_sync[RX_CH_0] == 1)? RX_CH_0 : RX_CH_1);

        DEBUG_CPRINT(("\nSBAND TIME TM_RD_RX_ST_2"));		/** RX long timer ON **/
        log_id(LOG_INFO_L1,LOG_COMMS,SBAND_TIME_TM_RD_RX_ST_2);
        os_timer_start(sband_rx_on_timer, sband_rssi_cfg.long_rx_on_tmr);
    }
    else
    {
        /** Check if the RSSI measured is in a valid range */
        if(rx_rssi[curr_rx][rssi_idx[curr_rx]] > sband_rssi_cfg.rssi_min)
        {
            DEBUG_CPRINT(("\nSBAND TIME TM_RD_RX_ST_3"));
            log_id(LOG_INFO_L1,LOG_COMMS,SBAND_TIME_TM_RD_RX_ST_3);
            valid_rssi[curr_rx]++;

            inv_rssi[curr_rx] = 0;

            /** Check if the minimum number of RSSI samples available for averaging */
            if(valid_rssi[curr_rx] >= sband_rssi_cfg.valid_rssi_cnt)
            {
                DEBUG_CPRINT(("\nSBAND TIME TM_RD_RX_ST_4"));
                log_id(LOG_INFO_L1,LOG_COMMS,SBAND_TIME_TM_RD_RX_ST_4);

                /** Compute avergae RSSI */
                avg_rssi[curr_rx] = comms_sband_get_avg_rssi(curr_rx);

                DEBUG_CPRINT(("curr_rx %d\n", curr_rx));
                log_id_with_one_arg(LOG_INFO_L2,LOG_COMMS,CURR_RX__u8_,curr_rx);
                DEBUG_CPRINT(("avrg rssi %f\n", avg_rssi[curr_rx] ));
                log_id_with_float(LOG_INFO_L2,LOG_COMMS,AVG_RSSI_u32,avg_rssi[curr_rx]);

                /** Update validity of average RSSI */
                avg_rssi_valid[curr_rx] = 1;

                /** Check if the average RSSI is above typical threshold */
                if(avg_rssi[curr_rx] >= sband_rssi_cfg.rssi_typ)
                {
                    DEBUG_CPRINT(("\nSBAND TIME TM_RD_RX_ST_5"));
                    log_id(LOG_INFO_L1,LOG_COMMS,SBAND_TIME_TM_RD_RX_ST_5);

                    /** Check Average RSSI presence of alternating RX */
                    if((1 == avg_rssi_valid[((curr_rx + 1)&0x01)])&&(avg_rssi[((curr_rx+1)&0x01)] != 0))
                    {
                        DEBUG_CPRINT(("\nSBAND TIME TM_RD_RX_ST_6"));
                        log_id(LOG_INFO_L1,LOG_COMMS,SBAND_TIME_TM_RD_RX_ST_6);

                        /** Average RSSI comparison for 2 RX ports */
                        if(avg_rssi[curr_rx] > avg_rssi[((curr_rx+1)&0x01)])
                        {
                            DEBUG_CPRINT(("\nSBAND TIME TM_RD_RX_ST_7"));
                            log_id(LOG_INFO_L1,LOG_COMMS,SBAND_TIME_TM_RD_RX_ST_7);

                            /** RX long timer ON **/
                            os_timer_start(sband_rx_on_timer, sband_rssi_cfg.long_rx_on_tmr);
#ifdef COMMS_TIME_DEBUG 
                            get_crnt_time_date(&tim_get_rs_hlr);
                            DEBUG_CPRINT(("\nSBAND TIME L_RX_ON TMR ENT %d:%d:%d - RX_ON_TMR %d",tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds, sband_rssi_cfg.long_rx_on_tmr));
                            log_id_with_four_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_L_RX_ON_TMR_ENT_u8__u8__u8__RX_ON_TMR__u8_,tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds, sband_rssi_cfg.long_rx_on_tmr);
#endif

                        }
                        else
                        {
                            DEBUG_CPRINT(("\nSBAND TIME TM_RD_RX_ST_8"));
                            log_id(LOG_INFO_L1,LOG_COMMS,SBAND_TIME_TM_RD_RX_ST_8);
                            DEBUG_CPRINT(("in RSSI measured below avg range\n"));
                            log_id(LOG_INFO_L2,LOG_COMMS,RSSI_MEASURED_BELOW_AVG_RANGE);

                            comms_sband_switch_rx_cfg();

                            /** RX long timer ON **/
                            os_timer_start(sband_rx_on_timer, sband_rssi_cfg.long_rx_on_tmr);
#ifdef COMMS_TIME_DEBUG
                            get_crnt_time_date(&tim_get_rs_hlr);
                            DEBUG_CPRINT(("\nSBAND TIME L_RX_ON TMR ENT %d:%d:%d - RX_ON_TMR %d",tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds, sband_rssi_cfg.long_rx_on_tmr));
                            log_id_with_four_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_L_RX_ON_TMR_ENT_u8__u8__u8__RX_ON_TMR__u8_,tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds, sband_rssi_cfg.long_rx_on_tmr);
#endif
                        }

                    }
                    else
                    {
                        DEBUG_CPRINT(("Set alternate RX "));
                        log_id(LOG_INFO_L1,LOG_COMMS,SET_ALTERNATE_RX);
                        comms_sband_switch_rx_cfg();

                        /** RX short timer ON **/
                        os_timer_start(sband_rx_on_timer, sband_rssi_cfg.short_rx_on_tmr);
#ifdef COMMS_TIME_DEBUG
                        get_crnt_time_date(&tim_get_rs_hlr);
                        DEBUG_CPRINT(("\nSBAND TIME S_RX_ON TMR ENT %d:%d:%d - RX_ON_TMR %d",tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds, sband_rssi_cfg.short_rx_on_tmr));
                        log_id_with_four_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_S_RX_ON_TMR_ENT_u8__u8__u8__RX_ON_TMR__u8_,tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds, sband_rssi_cfg.short_rx_on_tmr);
#endif

                    }
                }
                else
                {
                    DEBUG_CPRINT(("Above Typ Threshold context\n"));
                    log_id(LOG_INFO_L2,LOG_COMMS,ABOVE_TYP_THERSHOLD_CONTEXT);

                    comms_sband_switch_rx_cfg();

                    /** RX short timer ON **/
                    os_timer_start(sband_rx_on_timer, sband_rssi_cfg.short_rx_on_tmr);
#ifdef COMMS_TIME_DEBUG
                    get_crnt_time_date(&tim_get_rs_hlr);
                    DEBUG_CPRINT(("\nSBAND TIME S_RX_ON TMR ENT %d:%d:%d - RX_ON_TMR %d",tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds, sband_rssi_cfg.short_rx_on_tmr));
                    log_id_with_four_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_S_RX_ON_TMR_ENT_u8__u8__u8__RX_ON_TMR__u8_,tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds, sband_rssi_cfg.short_rx_on_tmr);
#endif
                }

            }
        }
        else
        {
            inv_rssi[curr_rx] ++;

            if(inv_rssi[curr_rx] >= sband_rssi_cfg.inv_rssi_cnt)
            {
                comms_sband_switch_rx_cfg();
                os_timer_start(sband_rx_on_timer, sband_rssi_cfg.short_rx_on_tmr);
#ifdef COMMS_TIME_DEBUG
                get_crnt_time_date(&tim_get_rs_hlr);
                DEBUG_CPRINT(("\nSBAND TIME S_RX_ON TMR ENT %d:%d:%d - RX_ON_TMR %d",tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds, sband_rssi_cfg.short_rx_on_tmr));
                log_id_with_four_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_S_RX_ON_TMR_ENT_u8__u8__u8__RX_ON_TMR__u8_,tim_get_rs_hlr.hour, tim_get_rs_hlr.minute, tim_get_rs_hlr.seconds, sband_rssi_cfg.short_rx_on_tmr);
#endif
            }
        }
    }

    rssi_idx[RX_CH_0] = (rssi_idx[RX_CH_0] + 1 ) % MAX_RSSI_STORE; /** TODO Change macro to configurable length */
    rssi_idx[RX_CH_1] = (rssi_idx[RX_CH_1] + 1 ) % MAX_RSSI_STORE;

    xlinks_rx_ch_en[0] = sband_serv_device_conf.RcvCtr_0.ChSwitchOn_0;
    xlinks_rx_ch_en[1] = sband_serv_device_conf.RcvCtr_0.ChSwitchOn_1;

    return 0;
}

/**
 * @brief Get current S-band receiver.
 *
 * @return ID of current active S-band receiver.
*/
uint8_t comms_sband_get_curr_rx(void)
{
    return curr_rx;
}


/**
 * @brief Enable S-band receiver port selection.
 *
 * @param rx_sel Receiver port selection mode.
 * @return Status of receiver port selection configuration. 
*/
uint8_t comms_sband_rx_port_sel_enb(uint8_t rx_sel)
{
    uint8_t status = 0;

    status = sband_proc_tc(SERVICE_GET|SERVICE_DEVICE_CONF);

    if(rx_sel)
    {

        sband_serv_device_conf.RcvCtr_0.ChSwitchOn_1 = 1;
        sband_serv_device_conf.RcvCtr_0.ChSwitchOn_0 = 0;
    }
    else
    {
        sband_serv_device_conf.RcvCtr_0.ChSwitchOn_1 = 0;
        sband_serv_device_conf.RcvCtr_0.ChSwitchOn_0 = 1;
    }

    xlinks_rx_ch_en[0] = sband_serv_device_conf.RcvCtr_0.ChSwitchOn_0;
    xlinks_rx_ch_en[1] = sband_serv_device_conf.RcvCtr_0.ChSwitchOn_1;

    status = sband_proc_tc_pld((SERVICE_SET|SERVICE_DEVICE_CONF), (uint8_t*)&sband_serv_device_conf);

    os_timer_stop(sband_rx_on_timer);
    os_timer_start(sband_tm_periodic_read, sband_tmr_cfg.sdr_tm_read_tmr);

    rssi_logic_en = 0;
    return status;
}
/**
 * @brief Select S-band receiver diversity mode. 
 *
 * @return Status of receiver diversity mode selection.
*/
uint8_t comms_sband_rx_port_sel_dsb(void)
{
    uint8_t success = 0;

    if(sband_tmr_cfg.sdr_tm_read_tmr >= sband_rssi_cfg.rssi_prd_tmr)
    {
        DEBUG_CPRINT(("\nsband rssi_prd_timer start at RX SEL DSB \n"));
        tm_store_cnt = sband_tmr_cfg.sdr_tm_read_tmr/sband_rssi_cfg.rssi_prd_tmr;
        os_timer_start(sband_tm_periodic_read, sband_rssi_cfg.rssi_prd_tmr);
    }
    else
    {
        //  DEBUG_CPRINT(("The TIMER START at TM_READ TIMER EXP ELSE %lu \n",tm_read_cnt ));
        tm_store_cnt = 1;
        os_timer_start(sband_tm_periodic_read, sband_tmr_cfg.sdr_tm_read_tmr);
    }
    rssi_logic_en = 1;

    return success;
}

/**
 * @brief Perform S-band xlink health check.
 * 
 * This function performs a health check on the S-band xlinks.
 * It checks parameters like RSSI, Doppler frequency, lock status,
 * data rate, etc. to determine health of the xlinks.
 *
 * Based on the checks, it sets the xlink health status which 
 * can be OK, Warning, or Critical. Warnings and failures are 
 * also logged.
*/
void sband_xlinks_health_check(void)
{
    uint8_t health_check = 0;
    uint32_t eps_req[2];
    eps_req[0] = HW_S_BAND;

    if(sband_serv_house_keep.HouseKeep.Temp.AD9361 > (sband_sens_cfg.temp_sensor[0].temp_sens_typ_thrs /100))
    {
        DEBUG_CPRINT(("TEMP exceeded AD9361: %d, %d, %d",sband_serv_house_keep.HouseKeep.Temp.AD9361, sband_sens_cfg.temp_sensor[0].temp_sens_typ_thrs, sband_sens_cfg.temp_sensor[0].temp_sens_max_thrs));
        if(sband_serv_house_keep.HouseKeep.Temp.AD9361 >= sband_sens_cfg.temp_sensor[0].temp_sens_max_thrs/100)
        {

            health_check |= 2;
        }
        else
        {
            health_check |= 1;
        }
    }
    if(sband_serv_house_keep.HouseKeep.Temp.EthPhy > (sband_sens_cfg.temp_sensor[1].temp_sens_typ_thrs / 100))
    {
        DEBUG_CPRINT(("TEMP exceeded EthPhy: %d, %d, %d",sband_serv_house_keep.HouseKeep.Temp.EthPhy, sband_sens_cfg.temp_sensor[1].temp_sens_typ_thrs, sband_sens_cfg.temp_sensor[1].temp_sens_max_thrs));
        if(sband_serv_house_keep.HouseKeep.Temp.EthPhy >= sband_sens_cfg.temp_sensor[1].temp_sens_max_thrs /100)
        {
            health_check |= 2;
        }
        else
        {
            health_check |= 1;
        }

    }
    if(sband_serv_house_keep.HouseKeep.Temp.Zynq > (sband_sens_cfg.temp_sensor[2].temp_sens_typ_thrs / 100))
    {
        DEBUG_CPRINT(("TEMP exceeded Zynq: %d, %d, %d",sband_serv_house_keep.HouseKeep.Temp.Zynq, sband_sens_cfg.temp_sensor[2].temp_sens_typ_thrs, sband_sens_cfg.temp_sensor[2].temp_sens_max_thrs));
        if(sband_serv_house_keep.HouseKeep.Temp.Zynq >= sband_sens_cfg.temp_sensor[2].temp_sens_max_thrs /100)
        {
            health_check |= 2;
        }
        else
        {
            health_check |= 1;
        }

    }


    if((sband_serv_house_keep.HouseKeep.Volt[0] != 0)&&((sband_serv_house_keep.HouseKeep.Volt[0] > ((float)sband_sens_cfg.volt_sensor[0].volt_sens_max_thrs/ 100))||(sband_serv_house_keep.HouseKeep.Volt[0]<((float)sband_sens_cfg.volt_sensor[0].volt_sens_min_thrs/ 100))))
    {
        DEBUG_CPRINT(("Volt_MAX_0 exceeded : %lf, %d, %d",sband_serv_house_keep.HouseKeep.Volt[0],  sband_sens_cfg.volt_sensor[0].volt_sens_max_thrs, sband_sens_cfg.volt_sensor[0].volt_sens_min_thrs));

        health_check |= 2;
    }
    if((sband_serv_house_keep.HouseKeep.Volt[1])&&((sband_serv_house_keep.HouseKeep.Volt[1] > ((float)sband_sens_cfg.volt_sensor[1].volt_sens_max_thrs / 100))||(sband_serv_house_keep.HouseKeep.Volt[1]<((float)sband_sens_cfg.volt_sensor[1].volt_sens_min_thrs/100))))
    {
        DEBUG_CPRINT(("Volt_MAX_1 exceeded : %lf, %d, %d",sband_serv_house_keep.HouseKeep.Volt[1],   sband_sens_cfg.volt_sensor[1].volt_sens_max_thrs, sband_sens_cfg.volt_sensor[1].volt_sens_min_thrs));

        health_check |= 2;
    }
    if((sband_serv_house_keep.HouseKeep.Volt[2])&&((sband_serv_house_keep.HouseKeep.Volt[2] > ((float)sband_sens_cfg.volt_sensor[2].volt_sens_max_thrs / 100))||(sband_serv_house_keep.HouseKeep.Volt[2]<((float)sband_sens_cfg.volt_sensor[2].volt_sens_min_thrs/100))))
    {
        DEBUG_CPRINT(("Volt_MAX_2 exceeded : %lf, %d, %d",sband_serv_house_keep.HouseKeep.Volt[2],   sband_sens_cfg.volt_sensor[2].volt_sens_max_thrs, sband_sens_cfg.volt_sensor[2].volt_sens_min_thrs));

        health_check |= 2;
    }
    if((sband_serv_house_keep.HouseKeep.Volt[3])&&((sband_serv_house_keep.HouseKeep.Volt[3] > ((float)sband_sens_cfg.volt_sensor[3].volt_sens_max_thrs / 100))||(sband_serv_house_keep.HouseKeep.Volt[3]<((float)sband_sens_cfg.volt_sensor[3].volt_sens_min_thrs / 100))))
    {
        DEBUG_CPRINT(("Volt_MAX_3 exceeded : %lf, %d, %d",sband_serv_house_keep.HouseKeep.Volt[3],   sband_sens_cfg.volt_sensor[3].volt_sens_max_thrs, sband_sens_cfg.volt_sensor[3].volt_sens_min_thrs));

        health_check |= 2;
    }
    if((sband_serv_house_keep.HouseKeep.Volt[4])&&((sband_serv_house_keep.HouseKeep.Volt[4] > ((float)sband_sens_cfg.volt_sensor[4].volt_sens_max_thrs/100))||(sband_serv_house_keep.HouseKeep.Volt[4]<((float)sband_sens_cfg.volt_sensor[4].volt_sens_min_thrs/100))))
    {
        DEBUG_CPRINT(("Volt_MAX_4 exceeded : %lf, %d, %d",sband_serv_house_keep.HouseKeep.Volt[4],   sband_sens_cfg.volt_sensor[4].volt_sens_max_thrs, sband_sens_cfg.volt_sensor[4].volt_sens_min_thrs));

        health_check |= 2;
    }
    if((sband_serv_house_keep.HouseKeep.Volt[5])&&((sband_serv_house_keep.HouseKeep.Volt[5] > ((float)sband_sens_cfg.volt_sensor[5].volt_sens_max_thrs/100))||(sband_serv_house_keep.HouseKeep.Volt[5]<((float)sband_sens_cfg.volt_sensor[5].volt_sens_min_thrs/100))))
    {
        DEBUG_CPRINT(("Volt_MAX_5 exceeded : %lf, %d, %d",sband_serv_house_keep.HouseKeep.Volt[5],   sband_sens_cfg.volt_sensor[5].volt_sens_max_thrs, sband_sens_cfg.volt_sensor[5].volt_sens_min_thrs));

        health_check |= 2;
    }

    if(health_check == 1)
    {
        DEBUG_CPRINT(("\nSBAND TIME HELTH_CHK_1 %d\n", health_check));
        sband_gs_contact_status_upd_itc(SBAND_TC_TM_STOP_REQ,COMMS_SBAND_IQS);
        os_timer_start(sband_reinit_tmr, SBAND_REINIT_TMR);

        sband_iqs_tx_ON = 0;
        comms_sband_xlink_tx_on(sband_iqs_tx_ON);
    }
    else if(health_check >1)
    {
        eps_req[1] = PWR_OFF;
        DEBUG_CPRINT(("\nSBAND TIME HELTH_CHK > 1 %d\n", health_check));
        /** Commenting this as part of release, since we are getting value 0 from SBAND module */
        (void)eps_req;
        sband_send_ipc_pld(EPS_SET_CHNL_STATE,EPS_TASK,sizeof(eps_req),(uint8_t *)eps_req);
        err_detected(ERR_GROUP_COMMS, ERR_COMMS_SBAND_OFF_VOLT_TEMP_EXCEED);
        os_timer_start(sband_reinit_tmr, SBAND_REINIT_TMR);
    }
    else
    {
        /**Nothing to be done */
    }
}

void comms_sband_switch_rx_cfg(void)
{
    uint8_t status = 0;
    if(curr_rx == 0)
    {
        sband_serv_device_conf.RcvCtr_0.ChSwitchOn_0 = 0;
    }
    else
    {
        sband_serv_device_conf.RcvCtr_0.ChSwitchOn_1 = 0;
    }
    curr_rx = (curr_rx + 1) & 0x01;

    if(curr_rx == 0)
    {
        sband_serv_device_conf.RcvCtr_0.ChSwitchOn_0 = 1;
    }
    else
    {
        sband_serv_device_conf.RcvCtr_0.ChSwitchOn_1 = 1;
    }

    DEBUG_CPRINT(("curr_rx_switch context %d\n", curr_rx));
    status = sband_proc_tc_pld((SERVICE_SET|SERVICE_DEVICE_CONF), (uint8_t*)&sband_serv_device_conf);

    /**TODO Error handling for command failure */
    if(status != 0)
    {
        DEBUG_CPRINT(("Failed SET DEVICE CONFIG \n"));
        log_id(LOG_ERROR,LOG_COMMS,FAILED_SET_DEVICE_CONFIG);
    }

    sband_serv_start_rf_rcv.ip_address = xlink_get_udp_ip_addr();
    sband_serv_start_rf_rcv.port                   = 51004;			
    sband_serv_start_rf_rcv.send_format            = RF_RCV_SEND_CLTU;		
    sband_serv_start_rf_rcv.output_interface       = RF_RCV_OUTPUT_UDP;
    sband_serv_start_rf_rcv.Reserve                = 0;

    DEBUG_CPRINT(("\nTemp IP Address: %d\n",sband_serv_start_rf_rcv.ip_address));

    status = sband_proc_tc_pld((SERVICE_SET|SERVICE_START_RF_RCV), (uint8_t*)&sband_serv_start_rf_rcv);

    /**TODO Error handling for command failure */
    if(status != 0)
    {
        DEBUG_CPRINT(("Failed SET START RCV CONFIG \n"));
        log_id(LOG_ERROR,LOG_COMMS,FAILED_SET_DEVICE_CONFIG);
    }

}

void comms_sband_reset_rssi_proc(void)
{
    curr_rx = 0;
    rx_sync_state = 0;

    os_memset(&rx_rssi[0][0],0,(sizeof(float) *(MAX_RX_CH * MAX_RSSI_STORE)));
    os_memset(&rssi_idx[0],0,(sizeof(uint32_t) *(MAX_RX_CH)));
    os_memset(&valid_rssi[0],0,(sizeof(uint32_t) *(MAX_RX_CH)));
    os_memset(&inv_rssi[0],0,(sizeof(uint32_t) *(MAX_RX_CH)));
    os_memset(&avg_rssi_valid[0],0,(sizeof(uint8_t) *(MAX_RX_CH)));
    os_memset(&avg_rssi[0],0,(sizeof(float) *(MAX_RX_CH)));
}
