/**
 * @file comms_sband_tmr.c
 *
 * @brief This file has the S-Band driver FSM implemenation and the relevant 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 "comms_sband_tmr.h"
#include "comms_sband_intf.h"
#include "sdr_app_main.h"
#include "exo_common.h"
#include "logger.h"
#include "comms_sband_init.h"
#include "comms_ipc.h"
#include "exo_io_al_rtc_common.h"
#include "exo_io_al_sos_timer.h"
#include "exo_tctm_ipc.h"

sys_time_date_s tim_get_tmr;

extern s_sdr_tmr_cfg PLACE_IN_EXT_RAM_MEM sband_tmr_cfg;
extern uint8_t PLACE_IN_EXT_RAM_MEM beacon_en;

/** Flag denotes the scheduler based ground pass window status */

extern volatile uint8_t PLACE_IN_EXT_RAM_MEM sband_sch_gs_contact;
extern s_sdr_gpass_beacon_cfg PLACE_IN_EXT_RAM_MEM sband_gpass_cfg;


uint8_t PLACE_IN_EXT_RAM_MEM comms_otsu_gs_contact = 0;
uint8_t PLACE_IN_EXT_RAM_MEM comms_first_gs_contact = 0 ;
uint32_t sband_rep_cnt = 0;





/** Timer used for command wait in sband configuration */
os_timer_handle_ptr sband_cmd_wait_timer;

/** Timer used for tm store Periodicity Timer */
os_timer_handle_ptr sband_reinit_tmr;

/** Timer used for tm store Periodicity Timer */
os_timer_handle_ptr sband_tm_periodic_read;

/** Timer used for enable and periodic transmission of Beacon signal */
os_timer_handle_ptr sband_beacon_timer;

/** Timer used for enable and periodic transmission of Beacon signal */
os_timer_handle_ptr sband_beacon_enb_timer;

/** Timer used for enable and periodic transmission of Beacon signal */
os_timer_handle_ptr sband_beacon_rep_timer;

/** Timer used for RX on Timer */
os_timer_handle_ptr sband_rx_on_timer;

/** Timer used for transmit ON duration */
os_timer_handle_ptr sband_tx_tm_on;

/** Timer used for IQS transmit window ON duration */
os_timer_handle_ptr sband_tx_win_on;

/**
 * @brief Initialize S-Band timers.
 *
 * Creates timer instances for:
 * - RX window on 
 * - Beacon enable  
 * - Periodic TM read
 * - Re-init watchdog
 *
 */
int8_t comms_sband_timer_init(void)
{
    uint64_t time_diff = 0, epoch_time = 0;
    time_diff=time_diff;
    epoch_time=epoch_time;

    /** Timer creation for Beacon enable and periodic beacon transmission **/
    os_timer_create(&sband_cmd_wait_timer ,"sband_cmd_wait_timer ",ONESHOT,(ral_timer_cbfunc_t)sband_cmd_wait_tmr_exp_cb,NULL);

    /** Timer creation for Beacon enable and periodic beacon transmission **/
    os_timer_create(&sband_beacon_timer ,"sband_beacon_timer",ONESHOT,(ral_timer_cbfunc_t)sband_beacon_timer_exp_cb,NULL);

    /** Timer creation for Beacon enable and periodic beacon transmission **/
    os_timer_create(&sband_beacon_enb_timer ,"sband_beacon_enb_timer",ONESHOT,(ral_timer_cbfunc_t)sband_beacon_enb_timer_exp_hdlr,NULL);

    /** Timer creation for Beacon repetition interval transmission **/
    os_timer_create(&sband_beacon_rep_timer ,"sband_beacon_rep_timer",ONESHOT,(ral_timer_cbfunc_t)sband_beacon_rep_timer_exp_hdlr,NULL);

    /** Timer creation for S-Band Periodic read of telemetry or house keeping information for RSSI tracking and TM storage */
    os_timer_create(&sband_reinit_tmr,"sband_reinit_tmr",ONESHOT,(ral_timer_cbfunc_t)sband_reinit_tmr_exp_cb,NULL);

    /** Timer creation for S-Band Periodic read of telemetry or house keeping information for RSSI tracking and TM storage */
    os_timer_create(&sband_tm_periodic_read ,"sband_tm_periodic_read",ONESHOT,(ral_timer_cbfunc_t)sband_tm_periodic_read_cb,NULL);

    /** Timer creation for S-Band RX window ON duration short or long based on measure RSSI */
    os_timer_create(&sband_rx_on_timer ,"sband_rx_on_timer_cb",ONESHOT,(ral_timer_cbfunc_t)sband_rx_on_timer_cb,NULL);

    /** Timer creation for S-Band TX window ON duration. Upon expiry, S-band tx will be turned off (currently used for IQS)*/
    os_timer_create(&sband_tx_win_on,"sband_tx_win_on",ONESHOT,(ral_timer_cbfunc_t)sband_tx_win_on_cb,NULL);

    /** Timer creation for S-Band stored TM transmission duration, upon expiry, the received TM gets to storage mode*/
    os_timer_create(&sband_tx_tm_on,"sband_tx_tm_on",ONESHOT,(ral_timer_cbfunc_t)sband_tx_tm_on_cb,NULL);

#if 0 //def SBAND_BEACON_ENB

    //  if((!comms_first_gs_contact)&&(!comms_otsu_gs_contact))
    if(beacon_en)
    {
        time_diff = get_crnt_time_date_in_epoch();

        epoch_time = sband_permanant_timer_read();

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
        DEBUG_CPRINT(("S-Band current time:%llu",time_diff));

        time_1sthalf = time_diff & 0xFFFFFFFF;
        time_2ndhalf |= time_diff >> 32;

        log_id_with_one_arg(LOG_INFO_L2,LOG_COMMS,SBAND_CURRENT_TIME_u32_,time_1sthalf);
        log_id_with_one_arg(LOG_INFO_L2,LOG_COMMS,SBAND_CURRENT_TIME_u32_,time_2sthalf);
#pragma GCC diagnostic pop
        time_diff = time_diff - epoch_time;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
        DEBUG_CPRINT(("S-Band time diff: %llu, epoch: %llu, current time:%llu",time_diff,epoch_time,time_diff));
#pragma GCC diagnostic pop

        if(time_diff < (sband_tmr_cfg.beacon_enb_tmr>>1))
        {
            os_timer_start(sband_beacon_enb_timer,sband_tmr_cfg.beacon_enb_tmr);
            DEBUG_CPRINT(("S-Band timer started for 60 mins"));
            log_id(LOG_INFO_L1,LOG_COMMS,SBAND_TIMER_STARTED_FOR_60_MINS);
        }
        else
        {
            os_timer_start(sband_beacon_timer,sband_tmr_cfg.beacon_prd_tmr);
            DEBUG_CPRINT(("S-Band timer started for 4 mins"));
            log_id(LOG_INFO_L1,LOG_COMMS,SBAND_TIMER_STARTED_FOR_4_MINS);
        }
    }
    else
    {
        os_timer_start(sband_beacon_timer,sband_tmr_cfg.beacon_prd_tmr);
    }
#endif
    os_timer_start(sband_beacon_enb_timer,sband_tmr_cfg.beacon_enb_tmr);
    return 0;
}

/**
 * @brief call back function at short duration expiry
 * pass fsm state via IPC
 * @brief RX window on timer callback.  
 *
 * Enables S-Band RX when window opens:
 * - Configures radio for RX.
 * - Starts IQ thread.
 */
void sband_rx_on_timer_cb(void)
{
#ifdef COMMS_TIME_DEBUG 
    get_crnt_time_date(&tim_get_tmr);
    DEBUG_CPRINT(("\nSBAND TIME RX_on TMR EXT %d:%d:%d",tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds));
    log_id_with_three_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_RX_ON_TMR_ENT__u8__u8__u8_,tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds);
#endif
    sband_send_ipc(SBAND_RX_ON_TIMER_EXP,COMMS_SBAND_CTLR);
}

/**
 *
 * @brief call back function at beacon repitition interval expiry
 *
 */
void sband_beacon_rep_timer_exp_hdlr(void)
{
#ifdef COMMS_TIME_DEBUG
    get_crnt_time_date(&tim_get_tmr);
    DEBUG_CPRINT(("\nSBAND TIME BEC_REP TMR EXT %d:%d:%d",tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds));
    //log_id_with_three_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIMER_BEC_REP_TMR_EXT__u8__u8__u8_,tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds);
#endif

    sband_rep_cnt ++;
    /*conditional check for timer expiring */
    if((sband_gpass_cfg.gpass_beacon_tx_enb)&&(sband_sch_gs_contact))
    {
        if(sband_rep_cnt <= sband_gpass_cfg.beacon_tx_count)
        {
            sband_send_ipc(SBAND_REP_TMR_EXP,COMMS_SBAND_CTLR);
        }
        else
        {
            sband_rep_cnt = 0;
            sband_gs_contact_status_upd_itc(SBAND_TC_TM_ST_REQ,COMMS_SBAND_IQS);
        }
    }
    else
    {
        if(sband_rep_cnt <= sband_tmr_cfg.tx_data_rep_cnt)
        {
            sband_send_ipc(SBAND_REP_TMR_EXP,COMMS_SBAND_CTLR);
        }
        else
        {
            sband_rep_cnt = 0;
        }
    }
}

/**
 *
 * @brief call back function at beacon enb duration expiry
 * @brief Beacon enable timer callback.
 *
 * Handles beacon transmission:
 * - Enables beacon mode on radio.
 * - Sets beacon data pattern.
 * - Starts IQ thread. 
 */
void sband_beacon_enb_timer_exp_hdlr(void)
{
#ifdef COMMS_TIME_DEBUG 
    get_crnt_time_date(&tim_get_tmr);
    DEBUG_CPRINT(("\nSBAND TIME BEC_EN TMR EXT %d:%d:%d",tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds));
    log_id_with_three_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIMER_BEC_EN_TMR_EXT__u8__u8__u8_,tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds);
#endif

    os_timer_start(sband_beacon_timer,sband_tmr_cfg.beacon_prd_tmr);
}


/**
 * @brief This function handle the timer expiry of initial LEOP synchronisation timer
 * @brief Beacon timer periodic callback.  
 *
 * Performs periodic beacon tasks:
 * - Toggles beacon data pattern.
 * - Collects and stores beacon statistics.
 */
void sband_beacon_timer_exp_cb(void *ptr)
{
#ifdef COMMS_TIME_DEBUG
    get_crnt_time_date(&tim_get_tmr);
    DEBUG_CPRINT(("\nSBAND TIME BEC TMR EXT %d:%d:%d",tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds));
    log_id_with_three_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_BEC_TMR_EXT__u8__u8__u8_,tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds);
#endif

    sband_send_ipc(SBAND_TX_PERIODIC_BEACON_TMR_EXP,COMMS_SBAND_CTLR);
#if 0
    uint64_t time_diff = 0, epoch_time = 0;
    uint32_t time_1sthalf=0;
    uint32_t time_2ndhalf=0;

    time_diff = get_crnt_time_date_in_epoch();

    epoch_time = sband_permanant_timer_read();

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
    DEBUG_CPRINT(("S-Band current time:%llu",time_diff));
    time_1sthalf = time_diff & 0xFFFFFFFF;
    time_2ndhalf |= time_diff >> 32;

    log_id_with_one_arg(LOG_INFO_L2,LOG_COMMS,SBAND_CURRENT_TIME_u32_,time_1sthalf);
    log_id_with_one_arg(LOG_INFO_L2,LOG_COMMS,SBAND_CURRENT_TIME_u32_,time_2ndhalf);
#pragma GCC diagnostic pop
    time_diff = time_diff - epoch_time;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat"
    DEBUG_CPRINT(("S-Band time diff: %llu, epoch: %llu",time_diff,epoch_time ));
    time_1sthalf = time_diff & 0xFFFFFFFF;
    time_2ndhalf |= time_diff >> 32;

    log_id_with_one_arg(LOG_INFO_L2,LOG_COMMS,SBAND_CURRENT_TIME_u32_,time_1sthalf);
    log_id_with_one_arg(LOG_INFO_L2,LOG_COMMS,SBAND_CURRENT_TIME_u32_,time_2ndhalf);
#pragma GCC diagnostic pop
#endif
    os_timer_start(sband_beacon_timer,sband_tmr_cfg.beacon_prd_tmr);
    //get_crnt_time_date(&tim_get_tmr);
    //DEBUG_CPRINT(("\nSBAND TIME BEC TMR ENT %d:%d:%d",tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds));
    DEBUG_CPRINT(("SBAND: Beacon timer %d started",sband_tmr_cfg.beacon_prd_tmr));
    log_id_with_one_arg(LOG_INFO_L1,LOG_COMMS,SBAND_BEACON_TIMER_STARTED__u32,sband_tmr_cfg.beacon_prd_tmr);

}

/**
 * @brief This function is the callback function for the SBAND rx sync periodic timer
 *        This sync will be used to store parameter for every 2mins
 *  * Handles periodic TM collection: 
 * - Reads current radio statistics.
 * - Stores TM in buffer for transmission.
 */
void sband_tm_periodic_read_cb(void)
{
#ifdef COMMS_TIME_DEBUG
    get_crnt_time_date(&tim_get_tmr);
    DEBUG_CPRINT(("\nSBAND TIME TM_RD TMR EXT %d:%d:%d",tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds));
    log_id_with_three_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_TM_RD_TMR_EXT__u8__u8__u8_,tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds);
#endif
    sband_send_ipc(SBAND_TM_PERIODIC_READ,COMMS_SBAND_CTLR);
}

/**
 * @brief This function is the callback for sband window tx on timer expiry
 * @brief S-Band re-init watchdog timer callback.
 * 
 */
void sband_cmd_wait_tmr_exp_cb(void)
{
    sband_send_ipc(SBAND_CMD_TMR_EXP,COMMS_SBAND_CTLR);
    DEBUG_CPRINT(("*******sband_cmd_wait_tmr_cb********"));
}

/**
 * @brief This function is the callback for sband window tx on timer expiry
 */
void sband_reinit_tmr_exp_cb(void)
{
    sband_send_ipc(SBAND_REINIT_TMR_EXP,COMMS_SBAND_CTLR);
    DEBUG_CPRINT(("*******sband_reinit_tmr_cb********"));
}

/**
 * @brief This function is the callback for sband window tx on timer expiry
 */
void sband_tx_win_on_cb(void)
{
    sband_send_ipc(SBAND_IQS_TX_WIN_OFF,COMMS_SBAND_CTLR);
    DEBUG_CPRINT(("*******sband_tx_win_on_cb********"));
}

/**
 * @brief This function is the callback for sband tx on timer expiry
 */
void sband_tx_tm_on_cb(void)
{
#ifdef COMMS_TIME_DEBUG
    get_crnt_time_date(&tim_get_tmr);
    DEBUG_CPRINT(("\nSBAND TIME TM TMR EXT %d:%d:%d ",tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds));
    log_id_with_three_arg(LOG_INFO_L2,LOG_COMMS,SBAND_TIME_TM_TMR_EXT__u8__u8__u8_,tim_get_tmr.hour, tim_get_tmr.minute, tim_get_tmr.seconds);
#endif

    if(!sband_sch_gs_contact)
    {
        sband_gs_contact_status_upd_itc(SBAND_TC_TM_STOP_REQ,COMMS_SBAND_IQS);
        //os_timer_start(sband_tx_tm_on,sband_tmr_cfg.sdr_tm_tx_tmr);
        DEBUG_CPRINT(("\nSBAND_TX_TIMER_STOPPED TM send stopped \n"));
        log_id(LOG_INFO_L1,LOG_COMMS,SBAND_TX_TIMER_STOPPED_TM_SEND_STOPPED);
#ifdef S_BAND_SIM_CB
        // sdr_sim_upd_srs4_tm_prop_wo_tx();
#endif
    }
    else
    {
        os_timer_stop(sband_tx_tm_on);
        DEBUG_CPRINT(("\nSBAND_TX_TIMER_STOPPED TM send not stopped \n"));
        log_id(LOG_INFO_L1,LOG_COMMS,SBAND_TX_TIMER_STOPPED_TM_SEND_NOT_STOPPED);
    }

}
