// Copyright 2024 XMOS LIMITED.
#define DEBUG_PRINT_ENABLE 0
#include "debug_print.h"
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include <print.h>
#include <stdio.h>
#include <string.h>
#include <platform.h>
#include <xs1.h>
#include <xcore/chanend.h>
#include <xcore/channel.h>
#include <xcore/channel_streaming.h>
#include "xc_ptr.h"

#include "xua_conf.h"
#include "share_buffer.h"

extern uint32_t init_eq_data(unsigned sample_freq);

#if F1_MUSIC_UAC2 == 1 && DNR_ENABLE == 1
/* 改动原因：3 streaming chan + 1 普通 chan 传 us 192kHz（跨 tile 静态内存不共享） */
uint32_t uc_ssrc_ds_in;    /* tile[0]→tile[1] 192kHz mic */
uint32_t uc_ssrc_ds_out;   /* tile[1]→tile[0] 48kHz 降采样结果 */
uint32_t uc_ssrc_us_in;    /* tile[0]→tile[1] 48kHz DNR 后 */
uint32_t uc_ssrc_us_out;   /* tile[1]→tile[0] 192kHz 升采样结果（普通chan） */
#endif

void dnr_exchange_buffer(int32_t *data);

// sample_freq 作为首字发送给 tile[0] 的 dsp_main，用于采样率变化检测和 EQ 初始化
void buffer_exchange(chanend_t c_data, unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[], unsigned sample_freq) {
    unsigned data_in[4] = {0,0,0,0};
    unsigned data_out[4] = {0,0,0,0};
    data_in[0] = sampsFromUsbToAudio[0];
    data_in[1] = sampsFromUsbToAudio[1];
    data_in[2] = sampsFromAudioToUsb[0];
    data_in[3] = sampsFromAudioToUsb[1];
    chan_out_buf_word (c_data, data_in, 4);
    chan_in_buf_word  (c_data , data_out, 4);
    sampsFromUsbToAudio[0] = data_out[0];
    sampsFromUsbToAudio[1] = data_out[1];
    sampsFromAudioToUsb[0] = data_out[2];
    sampsFromAudioToUsb[1] = data_out[3];
}


void dsp_main (chanend_t c_data) {
    int play_input[NUM_USB_CHAN_OUT];
    int play_output[I2S_CHANS_DAC];
    int mic_input[I2S_CHANS_ADC];
    int mic_output[I2S_CHANS_ADC];
    int count = 0;
    unsigned ch[1] = {2};
    unsigned data_in[4] = {0,0,0,0};
    unsigned data_out[4] = {0,0,0,0};
#if F1_MUSIC_UAC2 == 1
    unsigned current_sample_freq = 192000;
#else
    unsigned current_sample_freq = 48000;
#endif

#if F1_MUSIC_UAC2 == 1 && DNR_ENABLE == 1
    static int mic_48k[2]      = {0, 0};
    static int us_cache[4][2]  = {{0}};
    static int us_cache_idx    = 4;   /* 4=无有效缓存输出静音；0-3=当前消费 pair 索引 */
    static int ds_tick         = 0;   /* 每拍+1，满4拍处理一次 48kHz */
    /* 改动原因：第一个 tick4 时 us_out 还没有数据，不能阻塞读；
     * 之后每个 tick4 先读上一批（已就绪）再触发下一批，规避同拍等待 us_stereo 计算延迟 */
    static int us_first_batch  = 1;
#endif

    init_eq_data(current_sample_freq);
    clear_ring_buffer(0);
    clear_ring_buffer(1);
    clear_ring_buffer(2);
    clear_ring_buffer(3);
#if F1_MUSIC_UAC2 == 1 && DNR_ENABLE == 1
            /* 改动原因：采样率变化时复位所有 SSRC 状态，下一批重新从头开始 */
            ds_tick        = 0;
            us_cache_idx   = 4;
            us_first_batch = 1;
#endif
 
    while (1) {
        chan_in_buf_word(c_data, data_in, 4);
        chan_out_buf_word(c_data, data_out, 4);

#if EQ_ENABLE == 1
        write_to_ring_buffer(0, data_in[0]);
        write_to_ring_buffer(1, data_in[1]);
        data_out[0] = read_from_ring_buffer(2);
        data_out[1] = read_from_ring_buffer(3);
//        data_out[0] = data_in[0];
//        data_out[1] = data_in[1];
#else
        data_out[0] = data_in[0];
        data_out[1] = data_in[1];
#endif

#if DNR_ENABLE == 1
  #if F1_MUSIC_UAC2 == 1
        /* F1: 192kHz→48kHz(DS)→DNR→48kHz→192kHz(US)
         *
         * 时序优化说明：
         *   原设计在 tick4 同一拍内"发 us_in → 等 us_stereo 计算 → 读8个 us_out"，
         *   us_stereo 在 tile[1] 独立线程运算需 2-5µs，导致 tick4 总延迟超过 5.2µs
         *   (192kHz 单拍周期)，buffer_exchange 响应超时引发噪音。
         *
         *   当前设计：每个 tick4 先读上一批已就绪的 8 个 us_out 字（us_rec_output_core
         *   在前 3 拍期间已完成并阻塞等待消费，读取近乎零延迟），再触发本批 ds→DNR→us_in。
         *   代价：录音延迟增加约 20.8µs（一个 48kHz 周期），人耳不可感知。
         */
        s_chan_out_word((chanend_t)uc_ssrc_ds_in, (uint32_t)data_in[2]);
        s_chan_out_word((chanend_t)uc_ssrc_ds_in, (uint32_t)data_in[3]);
        ds_tick++;

        if (ds_tick >= 4) {
            ds_tick = 0;

            if (!us_first_batch) {
                /* 读上一批 us_stereo 已生产的 4 对 192kHz（近乎无延迟）*/
                us_cache[0][0] = (int)chan_in_word((chanend_t)uc_ssrc_us_out);
                us_cache[0][1] = (int)chan_in_word((chanend_t)uc_ssrc_us_out);
                us_cache[1][0] = (int)chan_in_word((chanend_t)uc_ssrc_us_out);
                us_cache[1][1] = (int)chan_in_word((chanend_t)uc_ssrc_us_out);
                us_cache[2][0] = (int)chan_in_word((chanend_t)uc_ssrc_us_out);
                us_cache[2][1] = (int)chan_in_word((chanend_t)uc_ssrc_us_out);
                us_cache[3][0] = (int)chan_in_word((chanend_t)uc_ssrc_us_out);
                us_cache[3][1] = (int)chan_in_word((chanend_t)uc_ssrc_us_out);
                us_cache_idx = 0;
            }

            /* 处理当前批：ds→DNR→us_in，结果在下一个 tick4 读取 */
            mic_48k[0] = (int)s_chan_in_word((chanend_t)uc_ssrc_ds_out);
            mic_48k[1] = (int)s_chan_in_word((chanend_t)uc_ssrc_ds_out);
            dnr_exchange_buffer(mic_48k);
            s_chan_out_word((chanend_t)uc_ssrc_us_in, (uint32_t)mic_48k[0]);
            s_chan_out_word((chanend_t)uc_ssrc_us_in, (uint32_t)mic_48k[1]);

            us_first_batch = 0;
        }

        if (us_cache_idx < 4) {
            data_out[2] = us_cache[us_cache_idx][0];
            data_out[3] = us_cache[us_cache_idx][1];
            us_cache_idx++;
        } else {
            data_out[2] = 0;
            data_out[3] = 0;
        }
  #else
        dnr_exchange_buffer((int32_t *)&data_in[2]);
        data_out[2] = data_in[2];
        data_out[3] = data_in[3];
  #endif
#else
        data_out[2] = data_in[2];
        data_out[3] = data_in[3];
#endif
    }
}
