#include "app_config.h"
#include "system/includes.h"
#include "fm/fm_manage.h"
#include "rda5807/RDA5807.h"
#include "bk1080/BK1080.h"
#include "qn8035/QN8035.h"
#include "fm_inside/fm_inside.h"
#include "asm/audio_linein.h"
#include "audio_config.h"
#include "audio_dec/audio_dec_fm.h"
#if TCFG_APP_FM_EN


#define LOG_TAG_CONST       APP_FM
#define LOG_TAG             "[APP_FM]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"

static FM_INTERFACE *t_fm_hdl = NULL;
static FM_INTERFACE *fm_hdl = NULL;
static struct _fm_dev_info *fm_dev_info;
static struct _fm_dev_platform_data *fm_dev_platform_data;
int linein_dec_open(u8 source, u32 sample_rate);
void linein_dec_close(void);

int fm_dev_init(void *_data)
{
    fm_dev_platform_data = (struct _fm_dev_platform_data *)_data;
    return 0;

    fm_dev_info = (struct _fm_dev_info *)malloc(sizeof(struct _fm_dev_info));
    if (fm_dev_info == NULL) {
        printf("fm_dev_init info malloc err!");
        return -1;
    }

    fm_dev_platform_data = (struct _fm_dev_platform_data *)_data;
    memset(fm_dev_info, 0x00, sizeof(struct _fm_dev_info));
    fm_dev_info->iic_hdl = fm_dev_platform_data->iic_hdl;
    fm_dev_info->iic_delay = fm_dev_platform_data->iic_delay;

    /* iic_init(fm_dev_info->iic_hdl);

    extern void bk1080_test(void);
    bk1080_test(); */

    fm_manage_check_online();
    if (!fm_hdl) {
        /* printf("fm_manage could not find dev\n"); */
        return -1;
    } else {
        extern void wdt_clear();
        wdt_clear();
        memcpy(fm_dev_info->logo, fm_hdl->logo, strlen(fm_hdl->logo));
        /* printf("fm_manage found dev %s\n", fm_dev_info->logo); */

        /* fm_manage_init(); */
        /* fm_manage_set_fre(875); */
        /* fm_manage_mute(0); */
        /* u16 iii = 875; */
        /* while(!fm_manage_set_fre(iii) && (iii < 1080)) { */
        /* printf("fm fre no %d\n", iii); */
        /* iii++; */
        /* os_time_dly(1); */
        /* } */
        /* printf("fm fre %d\n", iii); */
        /* while(1) { */
        /* os_time_dly(1); */
        /* } */
    }

    return 0;
}

u8 fm_dev_iic_write(u8 w_chip_id, u8 register_address, u8 *buf, u32 data_len)
{
    u8 ret = 1;
    iic_start(fm_dev_info->iic_hdl);
    if (0 == iic_tx_byte(fm_dev_info->iic_hdl, w_chip_id)) {
        ret = 0;
        log_e("\n fm iic wr err 0\n");
        goto __gcend;
    }

    delay(fm_dev_info->iic_delay);

    if (0 == iic_tx_byte(fm_dev_info->iic_hdl, register_address)) {
        ret = 0;
        log_e("\n fm iic wr err 1\n");
        goto __gcend;
    }
    u8 *pbuf = buf;

    while (data_len--) {
        delay(fm_dev_info->iic_delay);

        if (0 == iic_tx_byte(fm_dev_info->iic_hdl, *pbuf++)) {
            ret = 0;
            log_e("\n fm iic wr err 2\n");
            goto __gcend;
        }
    }

__gcend:
    iic_stop(fm_dev_info->iic_hdl);

    return ret;
}

u8 fm_dev_iic_readn(u8 r_chip_id, u8 register_address, u8 *buf, u8 data_len)
{
    u8 read_len = 0;

    iic_start(fm_dev_info->iic_hdl);
    if (0 == iic_tx_byte(fm_dev_info->iic_hdl, (r_chip_id & 0x01) ? (r_chip_id - 1) : (r_chip_id))) {
        log_e("\n fm iic rd err 0\n");
        read_len = 0;
        goto __gdend;
    }


    delay(fm_dev_info->iic_delay);
    if (0 == iic_tx_byte(fm_dev_info->iic_hdl, register_address)) {
        log_e("\n fm iic rd err 1\n");
        read_len = 0;
        goto __gdend;
    }

    delay(fm_dev_info->iic_delay);
    iic_start(fm_dev_info->iic_hdl);
    if (0 == iic_tx_byte(fm_dev_info->iic_hdl, r_chip_id)) {
        log_e("\n fm iic rd err 2\n");
        read_len = 0;
        goto __gdend;
    }

    delay(fm_dev_info->iic_delay);

    for (; data_len > 1; data_len--) {
        *buf++ = iic_rx_byte(fm_dev_info->iic_hdl, 1);
        read_len ++;
    }

    *buf = iic_rx_byte(fm_dev_info->iic_hdl, 0);

__gdend:

    iic_stop(fm_dev_info->iic_hdl);
    delay(fm_dev_info->iic_delay);

    return read_len;
}


void fm_manage_check_online(void)
{
    /* printf("fm check online dev \n"); */
    /* printf("addr %x %x\n", fm_dev_begin, fm_dev_end); */
    ////先找外挂fm
    list_for_each_fm(t_fm_hdl) {
        /* printf("find %x %x %s\n", t_fm_hdl, t_fm_hdl->read_id((void *)fm_dev_info), t_fm_hdl->logo); */
        if (t_fm_hdl->read_id((void *)fm_dev_info) &&
            (memcmp(t_fm_hdl->logo, "fm_inside", strlen(t_fm_hdl->logo)))) {
            fm_hdl = t_fm_hdl;
            printf("fm find dev %s \n", t_fm_hdl->logo);
            return;
        }
    }
    /* printf("no ex fm dev !!!\n"); */

    list_for_each_fm(t_fm_hdl) {
        /* printf("# find %x %x %s\n", t_fm_hdl, t_fm_hdl->read_id((void *)fm_dev_info), t_fm_hdl->logo); */
        if (t_fm_hdl->read_id((void *)fm_dev_info) &&
            (!memcmp(t_fm_hdl->logo, "fm_inside", strlen(t_fm_hdl->logo)))) {
            fm_hdl = t_fm_hdl;
            printf("fm find dev %s \n", t_fm_hdl->logo);
            return;
        }
    }
}
/* early_initcall(fm_manage_check_online); */

int fm_manage_init()
{
    fm_dev_info = (struct _fm_dev_info *)malloc(sizeof(struct _fm_dev_info));
    if (fm_dev_info == NULL) {
        printf("fm_dev_init info malloc err!");
        return -1;
    }

    memset(fm_dev_info, 0x00, sizeof(struct _fm_dev_info));

#if TCHFG_SOFT_I2C_ENABLE
    fm_dev_info->iic_hdl = fm_dev_platform_data->iic_hdl;
    fm_dev_info->iic_delay = fm_dev_platform_data->iic_delay;
    iic_init(fm_dev_info->iic_hdl);
#endif

    fm_manage_check_online();
    if (!fm_hdl) {
        printf("fm_manage could not find dev\n");
        return -1;
    } else {
        memcpy(fm_dev_info->logo, fm_hdl->logo, strlen(fm_hdl->logo));
        printf("fm_manage found dev %s\n", fm_dev_info->logo);
    }

    if (fm_hdl) {
        fm_hdl->init((void *)fm_dev_info);
    }

    return 0;
}



int fm_manage_start()
{

    if (!fm_hdl || !fm_dev_info) {
        printf("fm_manage could not find dev\n");
        return -1;
    }
    if (memcmp(fm_dev_info->logo, "fm_inside", strlen(fm_dev_info->logo))) {//不开启内部收音开启linein
#if (TCFG_FM_INPUT_WAY != LINEIN_INPUT_WAY_ADC)
        if (!app_audio_get_volume(APP_AUDIO_STATE_MUSIC)) {
            audio_linein_mute(1);    //模拟输出时候，dac为0也有数据
        }
#endif
#if (TCFG_FM_INPUT_WAY == LINEIN_INPUT_WAY_ADC)
        linein_dec_open(TCFG_FMIN_LR_CH, 44100);
#else
        if (TCFG_FMIN_LR_CH & (BIT(0) | BIT(1))) {
            audio_linein0_open(TCFG_FMIN_LR_CH, 1);
        } else if (TCFG_FMIN_LR_CH & (BIT(2) | BIT(3))) {
            audio_linein1_open(TCFG_FMIN_LR_CH, 1);
        } else if (TCFG_FMIN_LR_CH & (BIT(4) | BIT(5))) {
            audio_linein2_open(TCFG_FMIN_LR_CH, 1);
        }
        audio_linein_gain(1);   // high gain
#endif
#if (TCFG_FM_INPUT_WAY != LINEIN_INPUT_WAY_ADC)
        if (app_audio_get_volume(APP_AUDIO_STATE_MUSIC)) {
            audio_linein_mute(0);
            app_audio_set_volume(APP_AUDIO_STATE_MUSIC, app_audio_get_volume(APP_AUDIO_STATE_MUSIC), 1);//防止无法调整
        }
        //模拟输出时候，dac为0也有数据
#endif

    } else {
        fm_dec_open(0xff, 37500);//打开内置收音解码通道
    }
    return 0;
}

static u16 cur_fmrx_freq = 0;
bool fm_manage_set_fre(u16 fre)
{
    if (fm_hdl) {
        cur_fmrx_freq = fre;
        return fm_hdl->set_fre((void *)fm_dev_info, fre);
    }
    return 0;
}

u16 fm_manage_get_fre()
{
    if (fm_hdl) {
        return  cur_fmrx_freq;
    }
    return 0;
}



void fm_manage_close(void)
{

    if (fm_hdl) {
        fm_hdl->close((void *)fm_dev_info);
        fm_hdl = NULL;
    }

    if (fm_dev_info != NULL) {
        free(fm_dev_info);
        fm_dev_info = NULL;
    }

    if (t_fm_hdl && memcmp(t_fm_hdl->logo, "fm_inside", strlen(t_fm_hdl->logo))) { //不使用内部收音开启linein
#if (TCFG_FM_INPUT_WAY == LINEIN_INPUT_WAY_ADC)
        linein_dec_close();
#else
        if (TCFG_FMIN_LR_CH & (BIT(0) | BIT(1))) {
            audio_linein0_close(TCFG_FMIN_LR_CH, 0);
        } else if (TCFG_FMIN_LR_CH & (BIT(2) | BIT(3))) {
            audio_linein1_close(TCFG_FMIN_LR_CH, 0);
        } else if (TCFG_FMIN_LR_CH & (BIT(4) | BIT(5))) {
            audio_linein2_close(TCFG_FMIN_LR_CH, 0);
        }
#endif

    }
}


void fm_manage_mute(u8 mute)
{
    if (fm_hdl) {
        fm_hdl->mute((void *)fm_dev_info, mute);
    }
}

#endif
