#if F1_MUSIC_UAC2 == 1

#include "ssrc_rec_core.h"
#include <xs1.h>
#include <platform.h>
#include <string.h>
#include "ssrc_coefs.h"
#include "ssrc_us_share_buf.h"

#ifndef SET_SAMPLE_FREQ
#define SET_SAMPLE_FREQ 1
#endif

#ifndef NUM_USB_CHAN_OUT
#define NUM_USB_CHAN_OUT 2
#endif

/* Assembly function declarations */
extern unsigned char ds_stereo(
    int32_t final_shr,
    int32_t *coefs,
    int32_t *data,
    streaming chanend c_in,
    streaming chanend c_out,
    int32_t num_phase);

extern unsigned char us_stereo(
    int32_t *coefs,
    int32_t *l_history,
    int32_t *r_history,
    streaming chanend c_in,
    int32_t history_offset,
    uint32_t ring_buffer_addr,
    uint32_t tail_addr,
    int32_t ring_buffer_size,
    int32_t num_phase,
    int32_t phase_size,
    int32_t final_shr);

#pragma unsafe arrays
void ds_rec_core(streaming chanend c_from_tile0, streaming chanend c_to_tile0)
{
    int32_t history[1057];
    unsigned char control_token;

    memset(history, 0, sizeof(history));
    set_core_high_priority_on();

    while (1) {
        control_token = ds_stereo(
            SSRC_DS4_48K_FINAL_SHR,
            ds4_48000_coefs,
            history,
            c_from_tile0,   /* c_in:  read 192kHz from tile[0] */
            c_to_tile0,     /* c_out: write 48kHz back to tile[0] */
            4
        );

        switch (control_token) {
        case SET_SAMPLE_FREQ:
            memset(history, 0, sizeof(history));
            {
                unsigned dummy;
                c_from_tile0 :> dummy;
            }
            soutct(c_to_tile0, SET_SAMPLE_FREQ);
            for (size_t i = 0; i < NUM_USB_CHAN_OUT * 3; ++i) {
                c_to_tile0 <: 0;
            }
            break;
        default:
            break;
        }
    }
}

#pragma unsafe arrays
void us_rec_core(streaming chanend c_us_in)
{
    int32_t l_history[64];
    int32_t r_history[64];
    unsigned char control_token;

    memset(l_history, 0, sizeof(l_history));
    memset(r_history, 0, sizeof(r_history));
    ssrc_us_share_reset();

    while (1) {
        /* 改动原因：us_stereo.S 是持续运行的生产者，只有收到控制 token 才返回。
         * 正常音频路径不要在此函数后面发送数据，否则永远执行不到。 */
        control_token = us_stereo(
            us4_48000_coefs,
            l_history, r_history,
            c_us_in,
            SSRC_US4_HISTORY_OFFSET,
            ssrc_us_share_get_buffer_addr(),
            ssrc_us_share_get_tail_addr(),
            SSRC_US_RB_WORDS - 32,
            SSRC_US4_NUM_PHASE,
            SSRC_US4_PHASE_SIZE,
            SSRC_US4_FINAL_SHR
        );

        switch (control_token) {
        case SET_SAMPLE_FREQ:
            memset(l_history, 0, sizeof(l_history));
            memset(r_history, 0, sizeof(r_history));
            ssrc_us_share_reset();
            {
                unsigned dummy;
                c_us_in :> dummy;
            }
            break;
        default:
            break;
        }
    }
}

void us_rec_output_core(chanend c_us_out)
{
    while (1) {
        /* 改动原因：C 函数封装 ring buffer，避免 XC 并行共享对象规则报错和 C/XC 指针 ABI 差异。 */
        c_us_out <: ssrc_us_share_pop_word_blocking();
    }
}

#endif
