rename app_usb_aud_fosi_c1_v71

This commit is contained in:
Steven Dan
2026-05-13 18:29:06 +08:00
parent db328853d1
commit b4de6d4f73
92 changed files with 13936 additions and 377 deletions

View File

@@ -0,0 +1,163 @@
cmake_minimum_required(VERSION 3.21)
include($ENV{XMOS_CMAKE_PATH}/xcommon.cmake)
include(${CMAKE_CURRENT_LIST_DIR}/mode_cal.cmake)
project(phaten_module)
set(APP_HW_TARGET xu316_qf60.xn)
include(${CMAKE_CURRENT_LIST_DIR}/../deps.cmake)
#set(APP_PCA_ENABLE ON)
set(SW_USB_VERSION -DBCD_DEVICE_J=1
-DBCD_DEVICE_M=0
-DBCD_DEVICE_N=0)
set(SW_FACT_VERSION -DBCD_DEVICE_J=5
-DBCD_DEVICE_M=5
-DBCD_DEVICE_N=7)
set(SW_USB_AUDIO_FLAGS ${EXTRA_BUILD_FLAGS} ${SW_USB_VERSION} -O3
-report
-lquadflash
-g
-lotp3
-DUART_TX_VALUE=0x4
-DUSB_TILE=tile[0]
-DADAT_TX_USE_SHARED_BUFF=1
-DXUA_QUAD_SPI_FLASH=1)
set(SW_FACT_AUDIO_FLAGS ${EXTRA_BUILD_FLAGS} ${SW_FACT_VERSION}
-O3
-report
-lquadflash
-g
-lotp3
-DUART_TX_VALUE=0x4
-DUSB_TILE=tile[0]
-DADAT_TX_USE_SHARED_BUFF=1
-DXUA_QUAD_SPI_FLASH=1)
LINK_DIRECTORIES(${CMAKE_CURRENT_LIST_DIR}/../../lib_dnr/lib_dnr)
set(APP_COMPILER_FLAGS_v71_uac2 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
-DI2S_CHANS_ADC=2
-DMIN_FREQ=48000
-DMAX_FREQ=48000
-DUSE_EX3D=1
-DF3_F4_FPS_UAC2=1
-DMIXER=0
-DUAC2_MODE=1
-ldnr_50ms
-llib_ex3d_all
-DEQ_EN=1
-DDNR_ENABLE=1
-DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=16
-DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=16
-DINPUT_FORMAT_COUNT=1
-DOUTPUT_FORMAT_COUNT=1
-DEX3D_SF_NUM=3
-DNUM_USB_CHAN_OUT=8
-DNUM_USB_CHAN_IN=2
-DNUM_EX3D_CHAN_OUT=2
-DMIN_VOLUME=0xE000
-DINPUT_VOLUME_CONTROL=1
-DOUTPUT_VOLUME_CONTROL=1
#-DDEBUG_MEMORY_LOG_ENABLED=1
-DXUA_DFU_EN=1
-DHID_DFU_EN=1
-DIR_SWITCHING_MODE
-DHID_CONTROLS=1)
set(APP_COMPILER_FLAGS_v71_uac1 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
-DI2S_CHANS_ADC=2
-DMIN_FREQ=48000
-DAUDIO_CLASS=1
-DMAX_FREQ=48000
-DUSE_EX3D=1
-DF3_F4_FPS_UAC2=1
-DMIXER=0
-DUAC2_MODE=1
-ldnr_50ms
-llib_ex3d_all
-DEQ_EN=1
-DDNR_ENABLE=1
-DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=32
-DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=32
-DINPUT_FORMAT_COUNT=1
-DOUTPUT_FORMAT_COUNT=1
-DEX3D_SF_NUM=3
-DNUM_USB_CHAN_OUT=8
-DNUM_USB_CHAN_IN=2
-DNUM_EX3D_CHAN_OUT=2
-DMIN_VOLUME=0xE000
-DINPUT_VOLUME_CONTROL=1
-DOUTPUT_VOLUME_CONTROL=1
#-DDEBUG_MEMORY_LOG_ENABLED=1
-DXUA_DFU_EN=1
-DHID_DFU_EN=1
-DIR_SWITCHING_MODE
-DHID_CONTROLS=1)
set(APP_INCLUDES src src/core src/extensions ../../lib_dnr/lib_dnr)
set(XMOS_SANDBOX_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
XMOS_REGISTER_APP()
###=========================================================================###
# Flash image generation
# Slot assignment (matches MODE_Fxx flag values in audiohw.xc):
# slot 1 = f3_f4_fps_uac2 (COAX_IN_FLAG = MODE_F3_F4_FPS_UAC2)
# slot 2 = f5_music_uac1 (UAC1_IN_FLAG = MODE_F5_MUSIC_UAC1) <- factory base
# slot 3 = f1_music_uac2 (OPT_IN_FLAG = MODE_F1_MUSIC_UAC2)
# slot 4 = f6_f7_fps_uac1 (USB_IN_FLAG = MODE_F6_F7_FPS_UAC1)
###=========================================================================###
set(APP_BIN_DIR ${CMAKE_CURRENT_LIST_DIR}/bin)
set(APP_BASE ${PROJECT_NAME})
set(XE_FACT ${APP_BIN_DIR}/fact/${APP_BASE}_fact.xe)
set(XE_F1 ${APP_BIN_DIR}/f1_music_uac2/${APP_BASE}_f1_music_uac2.xe)
set(XE_F3F4 ${APP_BIN_DIR}/f3_f4_fps_uac2/${APP_BASE}_f3_f4_fps_uac2.xe)
set(XE_F5 ${APP_BIN_DIR}/f5_music_uac1/${APP_BASE}_f5_music_uac1.xe)
set(XE_F6F7 ${APP_BIN_DIR}/f6_f7_fps_uac1/${APP_BASE}_f6_f7_fps_uac1.xe)
set(LOADER_OBJ ${CMAKE_CURRENT_LIST_DIR}/loader.o)
set(TARGET_XN ${CMAKE_CURRENT_LIST_DIR}/src/core/synido.xn)
# factory_<project>_<version>.bin — full factory image (base + 4 upgrade slots)
add_custom_target(factory_bin
COMMAND ${CMAKE_COMMAND} -E echo "xflash ${XE_FACT} --loader ${LOADER_OBJ} --upgrade 1 ${XE_F3F4} --upgrade 2 ${XE_F5} --upgrade 3 ${XE_F1} --upgrade 4 ${XE_F6F7} -o ${CMAKE_CURRENT_LIST_DIR}/factory_${APP_BASE}_${FW_VERSION}.bin"
COMMAND xflash ${XE_FACT} --loader ${LOADER_OBJ}
--upgrade 2 ${XE_F5}
--upgrade 3 ${XE_F1}
--upgrade 1 ${XE_F3F4}
--upgrade 4 ${XE_F6F7}
-o ${CMAKE_CURRENT_LIST_DIR}/factory_${APP_BASE}_${FW_VERSION}.bin
#DEPENDS f1_music_uac2 f3_f4_fps_uac2 f5_music_uac1 f6_f7_fps_uac1
COMMENT "Generating factory image: factory_${APP_BASE}_${FW_VERSION}.bin"
VERBATIM
)
# update_<project>_<version>.bin — DFU upgrade package (upgrade slots only)
add_custom_target(update_bin
COMMAND ${CMAKE_COMMAND} -E echo "xflash --factory-version 15.2 --target-file ${TARGET_XN} --upgrade 1 ${XE_F3F4} --upgrade 2 ${XE_F5} --upgrade 3 ${XE_F1} --upgrade 4 ${XE_F6F7} -o ${CMAKE_CURRENT_LIST_DIR}/update_${APP_BASE}_${FW_VERSION}.bin"
COMMAND xflash --factory-version 15.2 --target-file ${TARGET_XN}
--upgrade 2 ${XE_F5}
--upgrade 3 ${XE_F1}
--upgrade 1 ${XE_F3F4}
--upgrade 4 ${XE_F6F7}
-o ${CMAKE_CURRENT_LIST_DIR}/update_${APP_BASE}_${FW_VERSION}.bin
#DEPENDS f1_music_uac2 f3_f4_fps_uac2 f5_music_uac1 f6_f7_fps_uac1
COMMENT "Generating update image: update_${APP_BASE}_${FW_VERSION}.bin"
VERBATIM
)

View File

@@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<Network xmlns="http://www.xmos.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.xmos.com http://www.xmos.com" ManuallySpecifiedRouting="true">
<Type>Board</Type>
<Name>XS3 MC Audio</Name>
<Declarations>
<Declaration>tileref tile[2]</Declaration>
<Declaration>tileref usb_tile</Declaration>
</Declarations>
<Packages>
<Package id="0" Type="XS3-UnA-1024-QF60A">
<Nodes>
<Node Id="0" InPackageId="0" Type="XS3-L16A-1024" Oscillator="24MHz" SystemFrequency="600MHz" referencefrequency="100MHz">
<Boot>
<Source Location="SPI:bootFlash"/>
</Boot>
<Tile Number="0" Reference="tile[0]">
<Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
<Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>
<!-- GPIO Ports -->
<!-- I2C -->
<Port Location="XS1_PORT_1D" Name="PORT_I2C_SCL"/>
<Port Location="XS1_PORT_1A" Name="PORT_I2C_SDA"/>
<!-- Audio Ports -->
<Port Location="XS1_PORT_1P" Name="PORT_MCLK_IN"/>
<Port Location="XS1_PORT_1L" Name="PORT_I2S_BCLK"/>
<Port Location="XS1_PORT_1M" Name="PORT_I2S_LRCLK"/>
<Port Location="XS1_PORT_1O" Name="PORT_I2S_DAC0"/>
<Port Location="XS1_PORT_1N" Name="PORT_I2S_ADC0"/>
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT_2"/>
<!-- UART Ports -->
<Port Location="XS1_PORT_4D" Name="PORT_MQA_RATE"/>
<Port Location="XS1_PORT_4A" Name="PORT_MQA_AUTH_STATE"/>
<Port Location="XS1_PORT_1P" Name="PORT_PLL_REF"/>
</Tile>
<Tile Number="1" Reference="tile[1]">
<Port Location="XS1_PORT_1A" Name="PORT_UART_RX"/>
<Port Location="XS1_PORT_1K" Name="PORT_UART_TX"/>
<Port Location="XS1_PORT_1F" Name="PORT_OPT_IN"/>
<Port Location="XS1_PORT_1D" Name="PORT_MCLK_IN_SPDIF_TX"/>
<Port Location="XS1_PORT_1B" Name="PORT_I2S_SLRCLK"/>
<Port Location="XS1_PORT_1C" Name="PORT_I2S_SBCLK"/>
<Port Location="XS1_PORT_1G" Name="PORT_COAX_IN"/>
</Tile>
</Node>
</Nodes>
</Package>
</Packages>
<Nodes>
<Node Id="2" Type="device:" RoutingId="0x8000">
<Service Id="0" Proto="xscope_host_data(chanend c);">
<Chanend Identifier="c" end="3"/>
</Service>
</Node>
</Nodes>
<Links>
<Link Encoding="2wire" Delays="4,4" Flags="XSCOPE">
<LinkEndpoint NodeId="0" Link="XL0"/>
<LinkEndpoint NodeId="2" Chanend="1"/>
</Link>
</Links>
<ExternalDevices>
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" Type="S25FL116K" PageSize="256" SectorSize="4096" NumPages="16384">
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
<Attribute Name="QE_REGISTER" Value="flash_qe_location_status_reg_0"/>
<Attribute Name="QE_BIT" Value="flash_qe_bit_6"/>
</Device>
</ExternalDevices>
<JTAGChain>
<JTAGDevice NodeId="0"/>
</JTAGChain>
</Network>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,32 @@
// Copyright 2026 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include "noise_gate_simple.h"
#define GATE_THRESHOLD_DB_MIN (-80)
#define GATE_THRESHOLD_DB_MAX (0)
// 10^(db/20) scaled to Q1.31, 4 dB resolution. Input dB is rounded to nearest
// 4 dB on lookup. 21 entries = 84 bytes of ROM.
static const int32_t k_db_to_q31_step4[21] = {
/* -80 */ 214748, 340354, 539423, 855025,
/* -64 */ 1355287, 2147484, 3403542, 5394226,
/* -48 */ 8550255, 13552872, 21474836, 34035417,
/* -32 */ 53942258, 85502547, 135528724, 214748365,
/* -16 */ 340354167, 539422577, 855025466, 1355287238,
/* 0 */ 2147483647
};
void gate_reset(simple_gate_t *g) {
g->env = 0;
g->gain = NOISE_GATE_Q31_ONE;
}
void gate_set_threshold_db(simple_gate_t *g, int8_t db) {
if (db > GATE_THRESHOLD_DB_MAX) db = GATE_THRESHOLD_DB_MAX;
if (db < GATE_THRESHOLD_DB_MIN) db = GATE_THRESHOLD_DB_MIN;
int idx = (db - GATE_THRESHOLD_DB_MIN + 2) >> 2; // round to nearest 4 dB
if (idx < 0) idx = 0;
if (idx > 20) idx = 20;
g->threshold_q31 = k_db_to_q31_step4[idx];
}

View File

@@ -0,0 +1,76 @@
// Copyright 2026 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
//
// Minimal, zero-latency Q1.31 noise gate. Coefficients are hard-coded for
// fs = 48 kHz; the struct only carries per-instance state.
//
// Algorithm:
// 1) Peak envelope tracker: single-pole EMA on |x|, separate rise/decay
// coefficients.
// 2) Hard-knee decision: target_gain = (env < threshold) ? 0 : 1.0.
// 3) Gain smoothing: EMA toward target_gain; fast when opening
// (gain rising), slow when closing (gain falling).
// 4) Output = x * gain (Q31 * Q31 -> Q31).
// Group delay: 0 samples.
//
// gate_process() lives in this header as static inline so the single call
// site in dnr_dsp.c inlines without function-call overhead — halves the
// tile-0 code footprint vs. an out-of-line implementation.
#ifndef NOISE_GATE_SIMPLE_H
#define NOISE_GATE_SIMPLE_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define NOISE_GATE_Q31_ONE 0x7FFFFFFF
// Alphas = 1 - exp(-1 / (tau * fs)) in Q1.31 at fs = 48 kHz.
#define NOISE_GATE_ENV_ATTACK_A 44291727 // 1 ms
#define NOISE_GATE_ENV_RELEASE_A 4469637 // 10 ms
#define NOISE_GATE_OPEN_A 22253774 // 2 ms (gain rising)
#define NOISE_GATE_CLOSE_A 558561 // 80 ms (gain falling)
typedef struct {
int32_t env; // Envelope state, Q1.31 unsigned magnitude.
int32_t gain; // Smoothed gain, Q1.31 (0..INT32_MAX).
int32_t threshold_q31; // Linear threshold, Q1.31 unsigned magnitude.
} simple_gate_t;
// Reset envelope and gain. Leaves threshold unchanged.
void gate_reset(simple_gate_t *g);
// Set threshold in integer dBFS, clamped to [-80, 0]. Quantised to 4 dB.
void gate_set_threshold_db(simple_gate_t *g, int8_t db);
// Single-sample gate. Inlined at the call site.
static inline int32_t gate_process(simple_gate_t *g, int32_t x) {
int32_t ax;
if (x == (int32_t)0x80000000) ax = NOISE_GATE_Q31_ONE;
else if (x < 0) ax = -x;
else ax = x;
int32_t edelta = ax - g->env;
int32_t env_a = (edelta > 0) ? NOISE_GATE_ENV_ATTACK_A : NOISE_GATE_ENV_RELEASE_A;
int64_t estep = (int64_t)env_a * (int64_t)edelta;
g->env += (int32_t)(estep >> 31);
int32_t target = (g->env < g->threshold_q31) ? 0 : NOISE_GATE_Q31_ONE;
int32_t gain_a = (target > g->gain) ? NOISE_GATE_OPEN_A : NOISE_GATE_CLOSE_A;
int32_t gdelta = target - g->gain;
int64_t gstep = (int64_t)gain_a * (int64_t)gdelta;
g->gain += (int32_t)(gstep >> 31);
int64_t y = (int64_t)x * (int64_t)g->gain;
return (int32_t)(y >> 31);
}
#ifdef __cplusplus
}
#endif
#endif // NOISE_GATE_SIMPLE_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,224 @@
#if DEBUG_MEMORY_LOG_ENABLED
#define DEBUG_PRINT_ENABLE 1
#else
#define DEBUG_PRINT_ENABLE 0
#endif
#include <xs1.h>
#include <platform.h>
#include <print.h>
#include <string.h>
#include "xmath/filter.h"
#include "stdio.h"
#include "xc_ptr.h"
#include "eq.h"
#include "share_buffer.h"
#include "debug_print.h"
#include "eq_flash_storage.h"
#if 0
#define DPRINTF(...) printf(__VA_ARGS__)
#else
#define DPRINTF(...)
#endif
#define LEN_FADE_ (2024)
// EQ Flash存储初始化标志
int eq_flash_initialized = 0;
extern unsigned int is_mode_changed(void);
extern void change_eq_mode(unsigned sample_freq);
extern void clear_eq_status(unsigned sample_freq, unsigned ch_no);
extern unsigned int g_request_eq_mode;
extern unsigned int g_eq_enable; // 改动原因添加EQ使能开关外部声明用于初始化时检查EQ状态
extern unsigned int g_saved_eq_mode; // 改动原因:添加保存模式外部声明,用于初始化时设置保存的模式
extern void debug_print_eq_params(unsigned sample_freq);
extern uint32_t get_reference_time(void);
extern void update_eq_post_gain(void);
extern unsigned int g_eq_sample_rate;
extern unsigned g_windows_detect_done;
extern unsigned g_dnr_init_flag;
extern unsigned g_ex3d_key_verified;
#pragma unsafe arrays
void dsp_core0(void)
{
unsigned t0,t1;
static int audio_in_samples[2]; // idx 0: input_samples
static int audio_out_samples[2]; // idx 0: input_samples
static unsigned int usb_to_dsp_ratio = 1;
static int buffer_in_active = 0;
static int buffer_out_active = 0;
static unsigned int sample_freq = 48000 ;
unsigned b_fade_in = 0;
unsigned u_in_step;
unsigned b_fade_out = 0;
unsigned u_out_step;
// EQ Flash存储初始化标志
delay_milliseconds(300);
unsigned windows_detect_done, dnr_init_flag, ex3d_key_verified;
GET_SHARED_GLOBAL(windows_detect_done, g_windows_detect_done);
#if DNR_ENABLE
GET_SHARED_GLOBAL(dnr_init_flag, g_dnr_init_flag);
#endif
#if USE_EX3D
GET_SHARED_GLOBAL(ex3d_key_verified, g_ex3d_key_verified);
#endif
while ((windows_detect_done == 0)
#if DNR_ENABLE
|| (dnr_init_flag == 0)
#endif
#if USE_EX3D
|| (ex3d_key_verified == 0)
#endif
) {
asm("nop");
GET_SHARED_GLOBAL(windows_detect_done, g_windows_detect_done);
#if DNR_ENABLE
GET_SHARED_GLOBAL(dnr_init_flag, g_dnr_init_flag);
#endif
#if USE_EX3D
GET_SHARED_GLOBAL(ex3d_key_verified, g_ex3d_key_verified);
#endif
}
#if EQ_EN
uint32_t time = get_reference_time(), time2;
// EQ Flash存储初始化 - 只在第一次运行时执行
if (eq_flash_initialized == 0) {
// 延迟更长时间确保QSPI Flash完全初始化
debug_printf("Initializing EQ Flash storage system\n");
// 初始化EQ Flash存储系统
if (eq_flash_init() == 0) {
debug_printf("EQ Flash storage initialized successfully\n");
init_mode_info();
eq_load_gain_and_names();
// 检查Flash中是否有EQ参数数据
debug_printf("Loading EQ parameters from Flash using simplified storage\n");
// 简化加载逻辑:每个模式只加载一次,会自动应用到所有采样率和通道
int loaded_modes = 0;
for (int mode = EQ_USER_MODE_MIN; mode <= EQ_USER_MODE_MAX; mode++) {
if (eq_load_all_params_and_calculate_coefficients(44100, mode) == 0) {
loaded_modes++;
debug_printf("Loaded mode %d parameters from Flash (applied to all sample rates and channels)\n", mode);
}
}
debug_printf("Loaded %d EQ modes from Flash successfully\n", loaded_modes);
// 从mode info里获取gain值并相应的赋值到eq数组的post gain
update_eq_post_gain();
// 从Flash加载并设置当前EQ模式和使能状态
// 改动原因修复EQ开关逻辑问题确保从Flash加载模式时正确设置g_saved_eq_mode和g_eq_enable
// eq_flash_load_current_mode()会同时加载模式并设置g_eq_enable
int saved_mode_result = eq_flash_load_current_mode();
// 改动原因确保g_eq_enable被正确加载无论模式加载是否成功
// eq_flash_load_current_mode()已经设置了g_eq_enable这里读取确认
unsigned int eq_enable = g_eq_enable;
if (saved_mode_result >= 0 && saved_mode_result <= 9) {
uint8_t saved_mode = (uint8_t)saved_mode_result;
debug_printf("Loaded current EQ mode %d and enable %d from Flash\n", saved_mode, eq_enable);
// 改动原因将eq_enable独立为全局开关所有模式共用一个开关
// 无论EQ是否启用都设置到Flash中保存的模式eq_enable只控制EQ处理开关
g_saved_eq_mode = saved_mode;
SET_SHARED_GLOBAL(g_request_eq_mode, saved_mode);
debug_printf("EQ initialization: Set mode to %d from Flash, EQ enable: %d (global switch, independent of mode)\n",
saved_mode, eq_enable);
} else {
// Flash加载失败时使用默认模式0EQ默认禁用
// 改动原因如果模式加载失败确保g_eq_enable也被设置为默认值0
g_saved_eq_mode = 0;
SET_SHARED_GLOBAL(g_request_eq_mode, 0);
g_eq_enable = 0;
eq_enable = 0; // 同步本地变量
debug_printf("Failed to load EQ mode from Flash, using default mode 0, EQ disabled (enable: %d)\n", eq_enable);
}
} else {
debug_printf("Failed to initialize EQ Flash storage system, continuing without Flash storage\n");
// 即使Flash初始化失败也标记为已初始化避免重复尝试
// 系统将继续运行只是不使用Flash存储功能
}
eq_single_param_database_init();
time2 = get_reference_time();
debug_printf("EQ Flash storage initialized time %lu\n", time2 - time);
eq_flash_initialized = 1;
}
while (1)
{
if(is_ring_buffer_empty(0) && is_ring_buffer_empty(1))
{
// delay_microseconds(1);
}
else
{
GET_SHARED_GLOBAL(sample_freq, g_eq_sample_rate);
if (sample_freq == 0) sample_freq = 48000;
audio_in_samples[0] = read_from_ring_buffer(0);
audio_in_samples[1] = read_from_ring_buffer(1);
if (is_mode_changed() && b_fade_out == 0 && b_fade_in == 0)
{
debug_printf("mode changed ====================== \n");
//debug_print_eq_params(sample_freq);
b_fade_out=1;
u_out_step=1;
}
audio_out_samples[0] = handler_eq_filter(sample_freq, 0, audio_in_samples[0]);
audio_out_samples[1] = handler_eq_filter(sample_freq, 1, audio_in_samples[1]);
if(b_fade_out)
{
audio_out_samples[0] /= LEN_FADE_;
audio_out_samples[0] *= (LEN_FADE_-u_out_step) ;
audio_out_samples[1] /= LEN_FADE_;
audio_out_samples[1] *= (LEN_FADE_-u_out_step) ;
++u_out_step;
}
if(b_fade_out == 1 && u_out_step == LEN_FADE_){
b_fade_out = 0;
change_eq_mode(sample_freq);
clear_eq_status(sample_freq, 0);
clear_eq_status(sample_freq, 1);
clear_ring_buffer(0);
clear_ring_buffer(1);
b_fade_in=1;
u_in_step=1;
}
if (b_fade_in)
{
audio_out_samples[0] /= LEN_FADE_;
audio_out_samples[0] *= (u_in_step) ;
audio_out_samples[1] /= LEN_FADE_;
audio_out_samples[1] *= (u_in_step);
if(++u_in_step >= LEN_FADE_){
b_fade_in = 0;
}
}
write_to_ring_buffer(2, audio_out_samples[0]);
write_to_ring_buffer(3, audio_out_samples[1]);
}
}
#endif
}

View File

@@ -0,0 +1,421 @@
#if DEBUG_MEMORY_LOG_ENABLED
#define DEBUG_PRINT_ENABLE 1
#else
#define DEBUG_PRINT_ENABLE 0
#endif
#include <xs1.h>
#include <platform.h>
#include <print.h>
#include <string.h>
#include "xmath/filter.h"
#include "stdio.h"
#include "xc_ptr.h"
#include "eq.h"
#include "share_buffer.h"
#include "debug_print.h"
#include "eq_flash_storage.h"
#include "eq_channel_protocol.h"
#if 0
#define DPRINTF(...) printf(__VA_ARGS__)
#else
#define DPRINTF(...)
#endif
#define LEN_FADE_ (2024)
extern unsigned int is_mode_changed(void);
extern void change_eq_mode(unsigned sample_freq);
extern void clear_eq_status(unsigned sample_freq, unsigned ch_no);
extern unsigned int g_request_eq_mode;
extern unsigned int g_eq_enable;
extern unsigned int g_saved_eq_mode;
extern void debug_print_eq_params(unsigned sample_freq);
extern uint32_t get_reference_time(void);
extern void update_eq_post_gain(void);
extern unsigned int g_eq_sample_rate;
extern unsigned g_windows_detect_done;
extern unsigned g_dnr_init_flag;
extern unsigned g_ex3d_key_verified;
extern unsigned int g_new_eq_mode;
extern unsigned int g_force_eq_mode_change;
/* ----------------------------------------------------------------
* eq_flash_init_task — 运行在 tile[0]
*
* 负责:
* 1) 等待系统就绪 (windows_detect / dnr / ex3d)
* 2) 从 QSPI Flash 加载 EQ 预设参数
* 3) 通过 c_eq_params channel 将加载的参数发送到 tile[1] 的 dsp_core0
* 4) 完成后退出 (不占用线程)
* ---------------------------------------------------------------- */
void eq_flash_init_task(chanend c_eq_params)
{
#if EQ_EN
delay_milliseconds(300);
/* ---- 等待系统就绪 ---- */
unsigned windows_detect_done, dnr_init_flag, ex3d_key_verified;
GET_SHARED_GLOBAL(windows_detect_done, g_windows_detect_done);
#if DNR_ENABLE
GET_SHARED_GLOBAL(dnr_init_flag, g_dnr_init_flag);
#endif
#if USE_EX3D
GET_SHARED_GLOBAL(ex3d_key_verified, g_ex3d_key_verified);
#endif
while ((windows_detect_done == 0)
#if DNR_ENABLE
|| (dnr_init_flag == 0)
#endif
#if USE_EX3D
|| (ex3d_key_verified == 0)
#endif
) {
asm("nop");
GET_SHARED_GLOBAL(windows_detect_done, g_windows_detect_done);
#if DNR_ENABLE
GET_SHARED_GLOBAL(dnr_init_flag, g_dnr_init_flag);
#endif
#if USE_EX3D
GET_SHARED_GLOBAL(ex3d_key_verified, g_ex3d_key_verified);
#endif
}
uint32_t time = get_reference_time(), time2;
/* ---- Flash 初始化 & 加载 ---- */
debug_printf("Initializing EQ Flash storage system\n");
unsigned int saved_mode = 0;
unsigned int eq_enable = 0;
if (eq_flash_init() == 0) {
debug_printf("EQ Flash storage initialized successfully\n");
init_mode_info();
eq_load_gain_and_names();
debug_printf("Loading EQ parameters from Flash using simplified storage\n");
int loaded_modes = 0;
for (int mode = EQ_USER_MODE_MIN; mode <= EQ_USER_MODE_MAX; mode++) {
if (eq_load_all_params_and_calculate_coefficients(44100, mode) == 0) {
loaded_modes++;
debug_printf("Loaded mode %d parameters from Flash\n", mode);
}
}
debug_printf("Loaded %d EQ modes from Flash successfully\n", loaded_modes);
update_eq_post_gain();
int saved_mode_result = eq_flash_load_current_mode();
eq_enable = g_eq_enable;
if (saved_mode_result >= 0 && saved_mode_result <= 9) {
saved_mode = (unsigned int)saved_mode_result;
debug_printf("Loaded current EQ mode %d and enable %d from Flash\n", saved_mode, eq_enable);
g_saved_eq_mode = saved_mode;
SET_SHARED_GLOBAL(g_request_eq_mode, saved_mode);
} else {
saved_mode = 0;
g_saved_eq_mode = 0;
SET_SHARED_GLOBAL(g_request_eq_mode, 0);
g_eq_enable = 0;
eq_enable = 0;
}
} else {
debug_printf("Failed to initialize EQ Flash storage system\n");
}
eq_single_param_database_init();
time2 = get_reference_time();
debug_printf("EQ Flash storage initialized time %lu\n", time2 - time);
/* ---- 通过 channel 将加载的参数发送到 tile[1] ---- */
/* 发送每个 mode / channel 的完整 band 参数 */
unsafe {
extern eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS];
for (int mode = 0; mode < NUM_EQ_MODES; mode++) {
for (int ch = 0; ch < NUM_EQ_CHANS; ch++) {
c_eq_params <: (unsigned)EQ_CMD_FLASH_LOAD_MODE;
c_eq_params <: (unsigned)mode;
c_eq_params <: (unsigned)ch;
c_eq_params <: (unsigned)sEQ_data_44100HZ[mode][ch].post_gain_db;
for (int b = 0; b < MAX_EQ_BANDS; b++) {
filter_params_t * unsafe bp = &sEQ_data_44100HZ[mode][ch].bands[b];
c_eq_params <: (unsigned)bp->type;
unsigned fc_u, q_u, bw_u, gain_u;
memcpy(&fc_u, &bp->fc, 4);
memcpy(&q_u, &bp->q, 4);
memcpy(&bw_u, &bp->bw, 4);
memcpy(&gain_u, &bp->gain, 4);
c_eq_params <: fc_u;
c_eq_params <: q_u;
c_eq_params <: bw_u;
c_eq_params <: gain_u;
c_eq_params <: (unsigned)bp->index;
}
}
}
/* 发送初始化完成信号 + 当前模式/使能 */
c_eq_params <: (unsigned)EQ_CMD_FLASH_INIT_COMPLETE;
c_eq_params <: (unsigned)saved_mode;
c_eq_params <: (unsigned)eq_enable;
}
debug_printf("EQ Flash init task: all params sent to tile[1], task exiting\n");
#endif /* EQ_EN */
}
/* ----------------------------------------------------------------
* 接收 channel 参数更新的内部处理函数 (tile[1])
* ---------------------------------------------------------------- */
#if EQ_EN
static void handle_eq_channel_cmd(chanend c_eq_params, unsigned cmd, unsigned sample_freq)
{
extern eq_mode_data_t sEQ_data_44100HZ[NUM_EQ_MODES][NUM_EQ_CHANS];
switch (cmd) {
case EQ_CMD_SET_MODE:
{
unsigned mode;
c_eq_params :> mode;
g_new_eq_mode = mode;
debug_printf("EQ channel: SET_MODE %d\n", mode);
break;
}
case EQ_CMD_SET_ENABLE:
{
unsigned enable;
c_eq_params :> enable;
g_eq_enable = enable;
debug_printf("EQ channel: SET_ENABLE %d\n", enable);
break;
}
case EQ_CMD_UPDATE_BAND:
{
unsigned mode, band_index, filter_type;
unsigned fc_u, q_u, bw_u, gain_u;
c_eq_params :> mode;
c_eq_params :> band_index;
c_eq_params :> filter_type;
c_eq_params :> fc_u;
c_eq_params :> q_u;
c_eq_params :> bw_u;
c_eq_params :> gain_u;
if (mode < NUM_EQ_MODES && band_index < MAX_EQ_BANDS) {
float fc, q, bw, gain;
memcpy(&fc, &fc_u, 4);
memcpy(&q, &q_u, 4);
memcpy(&bw, &bw_u, 4);
memcpy(&gain, &gain_u, 4);
for (int ch = 0; ch < NUM_EQ_CHANS; ch++) {
filter_params_t *bp = &sEQ_data_44100HZ[mode][ch].bands[band_index];
bp->type = (filter_type_t)filter_type;
bp->fc = fc;
bp->q = q;
bp->bw = bw;
bp->gain = gain;
bp->index = band_index;
}
/* 重算系数 */
calculate_current_mode_coefficients(sample_freq, mode);
debug_printf("EQ channel: UPDATE_BAND mode=%d band=%d\n", mode, band_index);
}
break;
}
case EQ_CMD_SET_GAIN:
{
unsigned mode;
unsigned gain_val;
c_eq_params :> mode;
c_eq_params :> gain_val;
if (mode < NUM_EQ_MODES) {
int32_t gain_db = (int32_t)gain_val;
sEQ_data_44100HZ[mode][0].post_gain_db = gain_db;
sEQ_data_44100HZ[mode][1].post_gain_db = gain_db;
debug_printf("EQ channel: SET_GAIN mode=%d gain=%d\n", mode, gain_db);
}
break;
}
case EQ_CMD_FORCE_REFRESH:
{
g_force_eq_mode_change = 1;
debug_printf("EQ channel: FORCE_REFRESH\n");
break;
}
case EQ_CMD_FLASH_LOAD_MODE:
{
unsigned mode, ch, post_gain;
c_eq_params :> mode;
c_eq_params :> ch;
c_eq_params :> post_gain;
if (mode < NUM_EQ_MODES && ch < NUM_EQ_CHANS) {
sEQ_data_44100HZ[mode][ch].post_gain_db = (int32_t)post_gain;
for (int b = 0; b < MAX_EQ_BANDS; b++) {
unsigned type_u, fc_u, q_u, bw_u, gain_u, idx_u;
c_eq_params :> type_u;
c_eq_params :> fc_u;
c_eq_params :> q_u;
c_eq_params :> bw_u;
c_eq_params :> gain_u;
c_eq_params :> idx_u;
filter_params_t *bp = &sEQ_data_44100HZ[mode][ch].bands[b];
bp->type = (filter_type_t)type_u;
memcpy(&bp->fc, &fc_u, 4);
memcpy(&bp->q, &q_u, 4);
memcpy(&bp->bw, &bw_u, 4);
memcpy(&bp->gain, &gain_u, 4);
bp->index = (uint8_t)idx_u;
}
} else {
/* mode/ch 越界, 仍然要读空 channel 数据 */
for (int b = 0; b < MAX_EQ_BANDS; b++) {
unsigned dummy;
c_eq_params :> dummy; c_eq_params :> dummy;
c_eq_params :> dummy; c_eq_params :> dummy;
c_eq_params :> dummy; c_eq_params :> dummy;
}
}
break;
}
case EQ_CMD_FLASH_INIT_COMPLETE:
{
unsigned saved_mode, eq_en;
c_eq_params :> saved_mode;
c_eq_params :> eq_en;
g_saved_eq_mode = saved_mode;
g_new_eq_mode = saved_mode;
SET_SHARED_GLOBAL(g_request_eq_mode, saved_mode);
g_eq_enable = eq_en;
/* 为所有模式计算初始系数 */
init_eq_data(48000);
debug_printf("EQ channel: FLASH_INIT_COMPLETE mode=%d enable=%d\n", saved_mode, eq_en);
break;
}
default:
debug_printf("EQ channel: unknown cmd 0x%x\n", cmd);
break;
}
}
#endif /* EQ_EN */
/* ----------------------------------------------------------------
* dsp_core0 — 运行在 tile[1]
*
* EQ 滤波主循环 + 通过 channel 接收参数更新
* ---------------------------------------------------------------- */
#pragma unsafe arrays
void dsp_core0(chanend c_eq_params)
{
unsigned t0,t1;
static int audio_in_samples[2];
static int audio_out_samples[2];
static unsigned int usb_to_dsp_ratio = 1;
static int buffer_in_active = 0;
static int buffer_out_active = 0;
static unsigned int sample_freq = 48000;
unsigned b_fade_in = 0;
unsigned u_in_step;
unsigned b_fade_out = 0;
unsigned u_out_step;
#if EQ_EN
/* 等待 Flash 初始化数据从 tile[0] 到达 */
{
unsigned flash_init_done = 0;
while (!flash_init_done) {
unsigned cmd;
c_eq_params :> cmd;
if (cmd == EQ_CMD_FLASH_INIT_COMPLETE) {
handle_eq_channel_cmd(c_eq_params, cmd, sample_freq);
flash_init_done = 1;
} else {
handle_eq_channel_cmd(c_eq_params, cmd, sample_freq);
}
}
}
clear_ring_buffer(0);
clear_ring_buffer(1);
clear_ring_buffer(2);
clear_ring_buffer(3);
while (1)
{
/* ---- 优先检查 channel 上的参数更新 (non-blocking) ---- */
select {
case c_eq_params :> unsigned cmd:
handle_eq_channel_cmd(c_eq_params, cmd, sample_freq);
break;
default:
break;
}
/* ---- 音频处理 ---- */
if(is_ring_buffer_empty(0) && is_ring_buffer_empty(1))
{
// 无数据, 继续轮询
}
else
{
GET_SHARED_GLOBAL(sample_freq, g_eq_sample_rate);
if (sample_freq == 0) sample_freq = 48000;
audio_in_samples[0] = read_from_ring_buffer(0);
audio_in_samples[1] = read_from_ring_buffer(1);
if (is_mode_changed() && b_fade_out == 0 && b_fade_in == 0)
{
debug_printf("mode changed ====================== \n");
b_fade_out=1;
u_out_step=1;
}
audio_out_samples[0] = handler_eq_filter(sample_freq, 0, audio_in_samples[0]);
audio_out_samples[1] = handler_eq_filter(sample_freq, 1, audio_in_samples[1]);
if(b_fade_out)
{
audio_out_samples[0] /= LEN_FADE_;
audio_out_samples[0] *= (LEN_FADE_-u_out_step) ;
audio_out_samples[1] /= LEN_FADE_;
audio_out_samples[1] *= (LEN_FADE_-u_out_step) ;
++u_out_step;
}
if(b_fade_out == 1 && u_out_step == LEN_FADE_){
b_fade_out = 0;
change_eq_mode(sample_freq);
clear_eq_status(sample_freq, 0);
clear_eq_status(sample_freq, 1);
clear_ring_buffer(0);
clear_ring_buffer(1);
b_fade_in=1;
u_in_step=1;
}
if (b_fade_in)
{
audio_out_samples[0] /= LEN_FADE_;
audio_out_samples[0] *= (u_in_step) ;
audio_out_samples[1] /= LEN_FADE_;
audio_out_samples[1] *= (u_in_step);
if(++u_in_step >= LEN_FADE_){
b_fade_in = 0;
}
}
write_to_ring_buffer(2, audio_out_samples[0]);
write_to_ring_buffer(3, audio_out_samples[1]);
}
}
#endif
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,67 @@
#ifndef __EQ_CHANNEL_PROTOCOL_H__
#define __EQ_CHANNEL_PROTOCOL_H__
/**
* @file eq_channel_protocol.h
* @brief EQ 参数跨 tile 通道通信协议
*
* 当 dsp_core0 运行在 tile[1] 时, process_send_params (tile[0]) 和
* AudioHwRemote (tile[0]) 通过 chanend c_eq_params 将 EQ 参数变更
* 发送到 tile[1] 的 dsp_core0.
*
* 通道数据格式: [cmd:32] [payload...]
* - 发送端先发 cmd word, 再发各命令对应的 payload words
* - 接收端在 dsp_core0 主循环中 non-blocking select 接收
*/
/*--- 命令码定义 ---*/
/** 切换EQ模式 (对应 HID 0x8A / 0x92)
* payload: [mode:32]
*/
#define EQ_CMD_SET_MODE 0x01
/** EQ使能开关 (对应 HID 0x9D)
* payload: [enable:32] (0=OFF, 1=ON)
*/
#define EQ_CMD_SET_ENABLE 0x02
/** 更新单个 band 参数 (对应 HID 0x8D)
* payload: [mode:32] [band_index:32] [filter_type:32]
* [fc_bits:32] [q_bits:32] [bw_bits:32] [gain_bits:32]
* float 值以 memcpy 方式打包到 uint32
*/
#define EQ_CMD_UPDATE_BAND 0x03
/** 设置模式增益 (对应 HID 0x8C 的增益部分)
* payload: [mode:32] [gain_db:32] (int32_t, 0 ~ -50)
*/
#define EQ_CMD_SET_GAIN 0x05
/** 强制刷新系数 (对应 apply_eq_band_params 中的 force_mode_change)
* payload: 无
*/
#define EQ_CMD_FORCE_REFRESH 0x06
/** Flash 初始化完成, 传输单个 mode 的完整参数
* payload: [mode:32] [ch:32] [post_gain_db:32]
* 每个 band (共 MAX_EQ_BANDS 个):
* [type:32] [fc_bits:32] [q_bits:32] [bw_bits:32] [gain_bits:32] [index:32]
* 发送完所有 mode/ch 后发 EQ_CMD_FLASH_INIT_COMPLETE
*/
#define EQ_CMD_FLASH_LOAD_MODE 0x10
/** Flash 初始化全部完成, 开始正常运行
* payload: [saved_mode:32] [eq_enable:32]
*/
#define EQ_CMD_FLASH_INIT_COMPLETE 0x11
/*--- 辅助宏 ---*/
/** 将 float 打包为 uint32_t 以便通过 channel 传输 */
#define FLOAT_TO_U32(f) ({ float _f = (f); uint32_t _u; memcpy(&_u, &_f, 4); _u; })
/** 将 uint32_t 解包为 float */
#define U32_TO_FLOAT(u) ({ uint32_t _u = (u); float _f; memcpy(&_f, &_u, 4); _f; })
#endif /* __EQ_CHANNEL_PROTOCOL_H__ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,255 @@
/**
* @file htr3236.c
* @brief HTR3236 36-Channel LED PWM Driver Implementation for XMOS
* @version 1.1
*/
#include "htr3236.h"
#include <xccompat.h>
#include <platform.h>
out port p_htr3235_sdb = PORT_HTR3236_SDB; /* 连接到HTR3236的SDB引脚用于控制其电源状态 */
/*=========================================================================
Gamma 校正查找表
-----------------------------------------------------------------------*/
static const uint8_t gamma_table_32[32] = {
0, 1, 2, 4, 6, 10, 13, 18,
22, 28, 33, 39, 46, 53, 61, 69,
78, 86, 96, 106, 116, 126, 138, 149,
161, 173, 186, 199, 212, 226, 240, 255
};
static const uint8_t gamma_table_64[64] = {
0, 1, 2, 3, 4, 5, 6, 7,
8, 10, 12, 14, 16, 18, 20, 22,
24, 26, 29, 32, 35, 38, 41, 44,
47, 50, 53, 57, 61, 65, 69, 73,
77, 81, 85, 89, 94, 99, 104, 109,
114, 119, 124, 129, 134, 140, 146, 152,
158, 164, 170, 176, 182, 188, 195, 202,
209, 216, 223, 230, 237, 244, 251, 255
};
/*=========================================================================
内部函数
-----------------------------------------------------------------------*/
/**
* @brief 写单字节到寄存器
*/
static int write_reg(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t reg, uint8_t data)
{
#if 0
uint8_t buf[2] = {reg, data};
size_t n;
i2c.write(dev->i2c_addr, buf, 2, n, 1);
if (n == 0)
{
return I2C_REGOP_DEVICE_NACK;
}
if (n < 2)
{
return I2C_REGOP_INCOMPLETE;
}
#endif
return I2C_REGOP_SUCCESS;
}
/**
* @brief 写多字节到寄存器 (支持自动地址递增)
*/
static int write_reg_bulk(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t start_reg,
const uint8_t *data, uint8_t len)
{
uint8_t buf[36 + 1];
size_t n;
#if 0
buf[0] = start_reg;
for (int i = 0; i < len; i++) {
buf[i + 1] = data[i];
}
i2c.write(dev->i2c_addr, buf, len + 1, n, 1);
if (n == 0)
{
return I2C_REGOP_DEVICE_NACK;
}
if (n < 2)
{
return I2C_REGOP_INCOMPLETE;
}
#endif
return I2C_REGOP_SUCCESS;
}
/**
* @brief 读取寄存器值
*/
static int read_reg(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t reg, i2c_regop_res_t &result)
{
uint8_t a_reg[1] = {reg};
uint8_t data[1] = {0};
size_t n;
i2c_res_t res;
unsafe
{
res = i2c.write(dev->i2c_addr, a_reg, 1, n, 0);
if (n != 1)
{
result = I2C_REGOP_DEVICE_NACK;
i2c.send_stop_bit();
return 0;
}
res = i2c.read(dev->i2c_addr, data, 1, 1);
}
if (res == I2C_ACK)
{
result = I2C_REGOP_SUCCESS;
}
else
{
result = I2C_REGOP_DEVICE_NACK;
}
return data[0];
}
/*=========================================================================
API 函数实现
-----------------------------------------------------------------------*/
void htr3236_init(htr3236_t *dev, uint8_t addr)
{
dev->i2c_addr = addr;
// 默认 SDB 拉高,使能芯片
//htr3236_hw_enable(dev);
}
void htr3236_hw_enable(htr3236_t *dev)
{
p_htr3235_sdb <: 1;
}
void htr3236_hw_disable(htr3236_t *dev)
{
p_htr3235_sdb <: 0;
}
int htr3236_software_wake(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c))
{
return write_reg(dev, i2c, HTR3236_REG_SHUTDOWN, HTR3236_NORMAL_OP);
}
int htr3236_software_shutdown(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c))
{
return write_reg(dev, i2c, HTR3236_REG_SHUTDOWN, HTR3236_SHUTDOWN_SOFT);
}
int htr3236_software_reset(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c))
{
return write_reg(dev, i2c, HTR3236_REG_RESET, 0x00);
}
int htr3236_set_pwm(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t channel, uint8_t brightness)
{
if (channel < 1 || channel > 36) {
return -1;
}
uint8_t reg = HTR3236_REG_PWM_START + (channel - 1);
return write_reg(dev, i2c, reg, brightness);
}
int htr3236_set_pwm_bulk(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t start_ch,
const uint8_t *values, uint8_t len)
{
if (start_ch < 1 || start_ch > 36 || len == 0) {
return -1;
}
// 检查是否会超出寄存器范围
if (start_ch + len - 1 > 36) {
return -1;
}
uint8_t start_reg = HTR3236_REG_PWM_START + (start_ch - 1);
return write_reg_bulk(dev, i2c, start_reg, values, len);
}
int htr3236_set_led_config(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t channel,
htr3236_current_t current, uint8_t enable)
{
if (channel < 1 || channel > 36) {
return -1;
}
uint8_t reg = HTR3236_REG_LED_CTRL_START + (channel - 1);
uint8_t data = (enable ? 1 : 0) | (current << 1);
return write_reg(dev, i2c, reg, data);
}
int htr3236_set_led_config_bulk(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t start_ch,
const uint8_t *configs, uint8_t len)
{
if (start_ch < 1 || start_ch > 36 || len == 0) {
return -1;
}
// 检查是否会超出寄存器范围
if (start_ch + len - 1 > 36) {
return -1;
}
uint8_t start_reg = HTR3236_REG_LED_CTRL_START + (start_ch - 1);
return write_reg_bulk(dev, i2c, start_reg, configs, len);
}
int htr3236_update(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c))
{
// 写入任意值到更新寄存器使配置生效
return write_reg(dev, i2c, HTR3236_REG_PWM_UPDATE, 0x00);
}
int htr3236_global_enable(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t enable)
{
uint8_t data = enable ? 1 : 0;
return write_reg(dev, i2c, HTR3236_REG_GLOBAL_CTRL, data);
}
int htr3236_set_frequency(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), htr3236_freq_t freq)
{
uint8_t data = (freq == HTR3236_FREQ_22KHZ) ? 1 : 0;
return write_reg(dev, i2c, HTR3236_REG_FREQ_SET, data);
}
uint8_t htr3236_gamma_32(uint8_t index)
{
if (index >= 32) {
index = 31;
}
return gamma_table_32[index];
}
uint8_t htr3236_gamma_64(uint8_t index)
{
if (index >= 64) {
index = 63;
}
return gamma_table_64[index];
}

View File

@@ -1,5 +1,5 @@
#if UART_DEBUG || DEBUG_MEMORY_LOG_ENABLED
#define DEBUG_PRINT_ENABLE 1
#define DEBUG_PRINT_ENABLE 0
#else
#define DEBUG_PRINT_ENABLE 0
#endif

View File

@@ -0,0 +1,233 @@
#include <stdlib.h>
#include <xs1.h>
#include <platform.h>
#include "lfs.h"
#include "rtos_qspi_flash.h"
#include "swlock.h"
#include "debug_print.h"
// variables used by the filesystem
lfs_t lfs;
lfs_file_t file;
swlock_t lfs_lock = SWLOCK_INITIAL_VALUE;
static rtos_qspi_flash_t qspi_flash_ctx_s;
#define FLASH_CLKBLK XS1_CLKBLK_3
#ifndef FS_BASE_ADDR
#define FS_BASE_ADDR 0x1da000
#endif
#define SECTOR_SIZE 4096
rtos_qspi_flash_t *qspi_flash_ctx = &qspi_flash_ctx_s;
__attribute__((fptrgroup(" local_block_device_read_fptr_grp")))
int local_block_device_read(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, void *buffer, lfs_size_t size)
{
unsigned address = (FS_BASE_ADDR + block * SECTOR_SIZE + off);
qspi_flash_ctx->read(qspi_flash_ctx, buffer, address, size);
return 0;
}
__attribute__((fptrgroup(" local_block_device_prog_fptr_grp")))
int local_block_device_prog(const struct lfs_config *c, lfs_block_t block,
lfs_off_t off, const void *buffer, lfs_size_t size)
{
unsigned address = (FS_BASE_ADDR + block * SECTOR_SIZE + off);
qspi_flash_ctx->write(qspi_flash_ctx, buffer, address, size);
return 0;
}
__attribute__((fptrgroup(" local_block_device_erase_fptr_grp")))
int local_block_device_erase(const struct lfs_config *c, lfs_block_t block)
{
unsigned address = (FS_BASE_ADDR + block * SECTOR_SIZE);
qspi_flash_ctx->erase(qspi_flash_ctx, address, SECTOR_SIZE);
return 0;
}
__attribute__((fptrgroup(" local_block_device_sync_fptr_grp")))
int local_block_device_sync(const struct lfs_config *c)
{
return 0;
}
// configuration of the filesystem is provided by this struct
const struct lfs_config cfg = {
// block device operations
.read = local_block_device_read,
.prog = local_block_device_prog,
.erase = local_block_device_erase,
.sync = local_block_device_sync,
// block device configuration
.read_size = 16,
.prog_size = 16,
.block_size = 4096,
.block_count = 128,
.cache_size = 16,
.lookahead_size = 16,
.block_cycles = 500,
};
int lfs_init(void) {
swlock_acquire(&lfs_lock);
rtos_qspi_flash_init(
qspi_flash_ctx,
FLASH_CLKBLK,
XS1_PORT_1B,
XS1_PORT_1C,
XS1_PORT_4B,
NULL);
// mount the filesystem
int err = lfs_mount(&lfs, &cfg);
// reformat if we can't mount the filesystem
// this should only happen on the first boot
if (err) {
debug_printf("no lfs partiton is found, formating ...\n");
lfs_format(&lfs, &cfg);
lfs_mount(&lfs, &cfg);
swlock_release(&lfs_lock);
return -1;
}
swlock_release(&lfs_lock);
return 0;
}
void lfs_deinit(void) {
swlock_acquire(&lfs_lock);
lfs_unmount(&lfs);
swlock_release(&lfs_lock);
}
#pragma stackfunction 1300
void lfs_read_config(unsigned char * config, unsigned char * buffer, unsigned size)
{
swlock_acquire(&lfs_lock);
debug_printf("lfs_read_config: %s, size: %d\n", config, size);
int result = lfs_file_open(&lfs, &file, config, LFS_O_RDWR | LFS_O_CREAT);
debug_printf("lfs_read_config: %s, result: %d\n", config, result);
if (result != 0) {
debug_printf("lfs_read_config: %s, open file failed\n", config);
swlock_release(&lfs_lock);
return;
}
debug_printf("lfs_read_config: %s, file opened\n", config);
result = lfs_file_read(&lfs, &file, buffer, size);
debug_printf("lfs_read_config: %s, result: %d\n", config, result);
if (result < 0) {
debug_printf("lfs_read_config: %s, read file failed, error: %d\n", config, result);
// Update: Added lfs_file_close to ensure file is closed even on error.
// Missing this caused subsequent open calls to assert/crash.
lfs_file_close(&lfs, &file);
swlock_release(&lfs_lock);
return;
}
lfs_file_close(&lfs, &file);
swlock_release(&lfs_lock);
}
#pragma stackfunction 1300
void lfs_write_config(unsigned char * config, unsigned char * buffer, unsigned size)
{
swlock_acquire(&lfs_lock);
debug_printf("lfs_write_config: %s, size: %d\n", config, size);
int result = lfs_file_open(&lfs, &file, config, LFS_O_RDWR | LFS_O_CREAT);
if (result != 0) {
debug_printf("lfs_write_config: open file failed\n");
swlock_release(&lfs_lock);
return;
}
result = lfs_file_rewind(&lfs, &file);
if (result != 0) {
debug_printf("lfs_write_config: rewind file failed\n");
// Update: Added lfs_file_close to prevent file remaining open if rewind fails.
lfs_file_close(&lfs, &file);
swlock_release(&lfs_lock);
return;
}
lfs_file_write(&lfs, &file, buffer, size);
lfs_file_close(&lfs, &file);
swlock_release(&lfs_lock);
}
// 检查文件是否存在
int lfs_file_exists(const char * file_path)
{
swlock_acquire(&lfs_lock);
lfs_file_t file;
int result = lfs_file_open(&lfs, &file, file_path, LFS_O_RDONLY);
if (result == 0) {
lfs_file_close(&lfs, &file);
swlock_release(&lfs_lock);
return 1; // 文件存在
}
swlock_release(&lfs_lock);
return 0; // 文件不存在
}
// EQ参数专用读写函数
void lfs_read_eq_config(const char * file_path, unsigned char * buffer, unsigned size)
{
lfs_file_open(&lfs, &file, file_path, LFS_O_RDONLY);
lfs_file_read(&lfs, &file, buffer, size);
lfs_file_close(&lfs, &file);
}
void lfs_write_eq_config(const char * file_path, unsigned char * buffer, unsigned size)
{
lfs_file_open(&lfs, &file, file_path, LFS_O_RDWR | LFS_O_CREAT);
lfs_file_rewind(&lfs, &file);
lfs_file_write(&lfs, &file, buffer, size);
lfs_file_close(&lfs, &file);
}
// 删除文件
int lfs_remove_file(const char * file_path)
{
return lfs_remove(&lfs, file_path);
}
// 创建目录(通过创建临时文件然后删除)
int lfs_create_directory(const char * dir_path)
{
char temp_file[256];
snprintf(temp_file, sizeof(temp_file), "%s/.dir", dir_path);
lfs_file_t file;
int result = lfs_file_open(&lfs, &file, temp_file, LFS_O_RDWR | LFS_O_CREAT);
if (result == 0) {
lfs_file_close(&lfs, &file);
lfs_remove(&lfs, temp_file);
return 0; // 成功
}
return -1; // 失败
}
#if 0
// read current count
uint32_t boot_count = 0;
lfs_file_open(&lfs, &file, "boot_count", LFS_O_RDWR | LFS_O_CREAT);
lfs_file_read(&lfs, &file, &boot_count, sizeof(boot_count));
// update boot count
boot_count += 1;
lfs_file_rewind(&lfs, &file);
for (int i = 0; i < 100; i++)
lfs_file_write(&lfs, &file, &boot_count, sizeof(boot_count));
// remember the storage is not updated until the file is closed successfully
lfs_file_close(&lfs, &file);
// release any resources we were using
lfs_unmount(&lfs);
// print the boot count
printf("boot_count: %d\n", boot_count);
#endif

View File

@@ -0,0 +1 @@
ninja: Entering directory `build'

View File

@@ -0,0 +1,836 @@
// Copyright 2012-2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include "xua.h" /* Device specific defines */
#ifdef EXCLUDE_USB_AUDIO_MAIN
/**
* @file main.xc
* @brief Top level for XMOS USB 2.0 Audio 2.0 Reference Designs.
* @author Ross Owen, XMOS Semiconductor Ltd
*/
#include <syscall.h>
#include <platform.h>
#include <xs1.h>
#include <xclib.h>
#include <print.h>
#ifdef XSCOPE
#include <xscope.h>
#endif
#if XUA_USB_EN
#include "xud_device.h" /* XMOS USB Device Layer defines and functions */
#include "xua_endpoint0.h"
#endif
#include "uac_hwresources.h"
#ifdef IAP
#include "i2c_shared.h"
#include "iap.h"
#endif
#if (XUA_SPDIF_RX_EN || XUA_SPDIF_TX_EN)
#include "spdif.h" /* From lib_spdif */
#endif
#if (XUA_ADAT_RX_EN)
#include "adat_rx.h"
#endif
#if (XUA_NUM_PDM_MICS > 0)
#include "xua_pdm_mic.h"
#endif
#if (XUA_DFU_EN == 1)
[[distributable]]
void DFUHandler(server interface i_dfu i, chanend ?c_user_cmd);
#endif
/* Audio I/O - Port declarations */
#if I2S_WIRES_DAC > 0
on tile[AUDIO_IO_TILE] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] =
{PORT_I2S_DAC0,
#endif
#if I2S_WIRES_DAC > 1
PORT_I2S_DAC1,
#endif
#if I2S_WIRES_DAC > 2
PORT_I2S_DAC2,
#endif
#if I2S_WIRES_DAC > 3
PORT_I2S_DAC3,
#endif
#if I2S_WIRES_DAC > 4
PORT_I2S_DAC4,
#endif
#if I2S_WIRES_DAC > 5
PORT_I2S_DAC5,
#endif
#if I2S_WIRES_DAC > 6
PORT_I2S_DAC6,
#endif
#if I2S_WIRES_DAC > 7
#error I2S_WIRES_DAC value is too large!
#endif
#if I2S_WIRES_DAC > 0
};
#else
#define p_i2s_dac null
#endif
#if I2S_WIRES_ADC > 0
on tile[AUDIO_IO_TILE] : buffered in port:32 p_i2s_adc[I2S_WIRES_ADC] =
{PORT_I2S_ADC0,
#endif
#if I2S_WIRES_ADC > 1
PORT_I2S_ADC1,
#endif
#if I2S_WIRES_ADC > 2
PORT_I2S_ADC2,
#endif
#if I2S_WIRES_ADC > 3
PORT_I2S_ADC3,
#endif
#if I2S_WIRES_ADC > 4
PORT_I2S_ADC4,
#endif
#if I2S_WIRES_ADC > 5
PORT_I2S_ADC5,
#endif
#if I2S_WIRES_ADC > 6
PORT_I2S_ADC6,
#endif
#if I2S_WIRES_ADC > 7
#error I2S_WIRES_ADC value is too large!
#endif
#if I2S_WIRES_ADC > 0
};
#else
#define p_i2s_adc null
#endif
#if CODEC_MASTER
on tile[AUDIO_IO_TILE] : buffered in port:32 p_lrclk = PORT_I2S_LRCLK;
on tile[AUDIO_IO_TILE] : buffered in port:32 p_bclk = PORT_I2S_BCLK;
#else
on tile[AUDIO_IO_TILE] : buffered out port:32 p_lrclk = PORT_I2S_LRCLK;
on tile[AUDIO_IO_TILE] : buffered out port:32 p_bclk = PORT_I2S_BCLK;
#endif
#if (!CODEC_MASTER) || XUA_SPDIF_TX_EN || XUA_ADAT_TX_EN || ((AUDIO_IO_TILE == XUD_TILE) && XUA_USB_EN)
/* Audio master clock input */
on tile[AUDIO_IO_TILE] : in port p_mclk_in = PORT_MCLK_IN;
#else
#define p_mclk_in null
#endif
#if (AUDIO_IO_TILE != XUD_TILE) && XUA_USB_EN
/* If audio I/O and USB running on different tiles we need a separate port for
* the master clock input (to use for USB async feedback calculation) */
on tile[XUD_TILE] : in port p_mclk_in_usb = PORT_MCLK_IN_USB;
#endif
#if XUA_USB_EN
on tile[XUD_TILE] : in port p_for_mclk_count = PORT_MCLK_COUNT;
#endif
#if (XUA_SPDIF_TX_EN)
on tile[SPDIF_TX_TILE] : buffered out port:32 p_spdif_tx = PORT_SPDIF_OUT;
#endif
#if (XUA_ADAT_TX_EN)
on stdcore[AUDIO_IO_TILE] : buffered out port:32 p_adat_tx = PORT_ADAT_OUT;
#endif
#if (XUA_ADAT_RX_EN)
on stdcore[XUD_TILE] : buffered in port:32 p_adat_rx = PORT_ADAT_IN;
#endif
#if (XUA_SPDIF_RX_EN)
on tile[XUD_TILE] : in port p_spdif_rx = PORT_SPDIF_IN;
#endif
#if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN) || (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
/* Reference to external clock multiplier */
on tile[PLL_REF_TILE] : out port p_pll_ref = PORT_PLL_REF;
#ifdef __XS3A__
on tile[AUDIO_IO_TILE] : port p_for_mclk_count_audio = PORT_MCLK_COUNT_2;
#else /* __XS3A__ */
#define p_for_mclk_count_audio null
#endif /* __XS3A__ */
#endif
#ifdef MIDI
on tile[MIDI_TILE] : port p_midi_tx = PORT_MIDI_OUT;
#if(MIDI_RX_PORT_WIDTH == 4)
on tile[MIDI_TILE] : buffered in port:4 p_midi_rx = PORT_MIDI_IN;
#elif(MIDI_RX_PORT_WIDTH == 1)
on tile[MIDI_TILE] : buffered in port:1 p_midi_rx = PORT_MIDI_IN;
#endif
#endif
#ifdef MIDI
on tile[MIDI_TILE] : clock clk_midi = CLKBLK_MIDI;
#endif
#if (XUA_SPDIF_TX_EN || XUA_ADAT_TX_EN)
on tile[SPDIF_TX_TILE] : clock clk_mst_spd = CLKBLK_SPDIF_TX;
#endif
#if (XUA_SPDIF_RX_EN)
on tile[XUD_TILE] : clock clk_spd_rx = CLKBLK_SPDIF_RX;
#endif
on tile[AUDIO_IO_TILE] : clock clk_audio_mclk = CLKBLK_MCLK; /* Master clock */
#if (AUDIO_IO_TILE != XUD_TILE) && XUA_USB_EN
/* Separate clock/port for USB feedback calculation */
on tile[XUD_TILE] : clock clk_audio_mclk_usb = CLKBLK_MCLK; /* Master clock */
#endif
on tile[AUDIO_IO_TILE] : clock clk_audio_bclk = CLKBLK_I2S_BIT; /* Bit clock */
#ifdef IAP
/* I2C ports - in a struct for use with module_i2c_shared & module_i2c_simple/module_i2c_single_port */
#ifdef PORT_I2C
on tile [IAP_TILE] : struct r_i2c r_i2c = {PORT_I2C};
#else
on tile [IAP_TILE] : struct r_i2c r_i2c = {PORT_I2C_SCL, PORT_I2C_SDA};
#endif
#endif
#if XUA_USB_EN
/* Endpoint type tables for XUD */
XUD_EpType epTypeTableOut[ENDPOINT_COUNT_OUT] = { XUD_EPTYPE_CTL | XUD_STATUS_ENABLE,
#if (NUM_USB_CHAN_IN > 0)
XUD_EPTYPE_ISO, /* Audio */
#endif
#ifdef MIDI
XUD_EPTYPE_BUL, /* MIDI */
#endif
#if HID_OUT_REQUIRED
XUD_EPTYPE_INT,
#endif
#ifdef IAP
XUD_EPTYPE_BUL, /* iAP */
#ifdef IAP_EA_NATIVE_TRANS
XUD_EPTYPE_BUL, /* EA Native Transport */
#endif
#endif
};
XUD_EpType epTypeTableIn[ENDPOINT_COUNT_IN] = { XUD_EPTYPE_CTL | XUD_STATUS_ENABLE,
#if (NUM_USB_CHAN_IN > 0)
XUD_EPTYPE_ISO,
#endif
#if (NUM_USB_CHAN_OUT > 0) && ((NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP))
XUD_EPTYPE_ISO, /* Async feedback endpoint */
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
XUD_EPTYPE_INT,
#endif
#ifdef MIDI
XUD_EPTYPE_BUL,
#endif
#if XUA_OR_STATIC_HID_ENABLED
XUD_EPTYPE_INT,
#endif
#ifdef IAP
XUD_EPTYPE_BUL | XUD_STATUS_ENABLE,
#ifdef IAP_INT_EP
XUD_EPTYPE_BUL | XUD_STATUS_ENABLE,
#endif
#ifdef IAP_EA_NATIVE_TRANS
XUD_EPTYPE_BUL | XUD_STATUS_ENABLE,
#endif
#endif
};
#endif /* XUA_USB_EN */
void thread_speed()
{
#ifdef FAST_MODE
#warning Building with fast mode enabled
set_thread_fast_mode_on();
#else
set_thread_fast_mode_off();
#endif
}
#ifdef XSCOPE
void xscope_user_init()
{
xscope_register(0, 0, "", 0, "");
xscope_config_io(XSCOPE_IO_BASIC);
}
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
void SpdifTxWrapper(chanend c_spdif_tx)
{
unsigned portId;
//configure_clock_src(clk, p_mclk);
// TODO could share clock block here..
// NOTE, Assuming SPDIF tile == USB tile here..
asm("ldw %0, dp[p_mclk_in_usb]":"=r"(portId));
asm("setclk res[%0], %1"::"r"(clk_mst_spd), "r"(portId));
configure_out_port_no_ready(p_spdif_tx, clk_mst_spd, 0);
set_clock_fall_delay(clk_mst_spd, 7);
start_clock(clk_mst_spd);
while(1)
{
spdif_tx(p_spdif_tx, c_spdif_tx);
}
}
#endif
void usb_audio_io(chanend ?c_aud_in,
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
chanend c_spdif_tx,
#endif
#if (MIXER)
chanend c_mix_ctl,
#endif
streaming chanend ?c_spdif_rx,
streaming chanend ?c_adat_rx,
chanend ?c_clk_ctl,
chanend ?c_clk_int
#if (XUD_TILE != 0) && (AUDIO_IO_TILE == 0) && (XUA_DFU_EN == 1)
, server interface i_dfu ?dfuInterface
#endif
#if (XUA_NUM_PDM_MICS > 0)
, chanend c_pdm_pcm
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, client interface pll_ref_if i_pll_ref
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, chanend c_audio_rate_change
#endif
#if ((XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
, port p_for_mclk_count_aud
, chanend c_sw_pll
#endif
)
{
#if (MIXER)
chan c_mix_out;
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
chan c_dig_rx;
chan c_audio_rate_change; /* Notification of new mclk freq to clockgen and synch */
#if XUA_USE_SW_PLL
/* Connect p_for_mclk_count_aud to clk_audio_mclk so we can count mclks/timestamp in digital rx*/
unsigned x = 0;
asm("ldw %0, dp[clk_audio_mclk]":"=r"(x));
asm("setclk res[%0], %1"::"r"(p_for_mclk_count_aud), "r"(x));
#endif /* XUA_USE_SW_PLL */
#endif /* (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) */
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE == AUDIO_IO_TILE)
chan c_spdif_tx;
/* Setup S/PDIF tx port - note this is done before par since sharing clock-block/port */
spdif_tx_port_config(p_spdif_tx, clk_audio_mclk, p_mclk_in, 7);
#endif
par
{
#if (MIXER && XUA_USB_EN)
/* Mixer cores(s) */
{
thread_speed();
mixer(c_aud_in, c_mix_out, c_mix_ctl);
}
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE == AUDIO_IO_TILE)
while(1)
{
spdif_tx(p_spdif_tx, c_spdif_tx);
}
#endif
/* Audio I/O core (pars additional S/PDIF TX Core) */
{
thread_speed();
#if (MIXER)
#define AUDIO_CHANNEL c_mix_out
#else
#define AUDIO_CHANNEL c_aud_in
#endif
XUA_AudioHub(AUDIO_CHANNEL, clk_audio_mclk, clk_audio_bclk, p_mclk_in, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc
#if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE)
, c_spdif_tx
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, c_dig_rx
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, c_audio_rate_change
#endif
#if (XUD_TILE != 0) && (AUDIO_IO_TILE == 0) && (XUA_DFU_EN == 1)
, dfuInterface
#endif
#if (XUA_NUM_PDM_MICS > 0)
, c_pdm_pcm
#endif
);
}
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
{
/* ClockGen must currently run on same tile as AudioHub due to shared memory buffer
* However, due to the use of an interface the pll reference signal port can be on another tile
*/
thread_speed();
clockGen( c_spdif_rx,
c_adat_rx,
i_pll_ref,
c_dig_rx,
c_clk_ctl,
c_clk_int,
c_audio_rate_change
#if XUA_USE_SW_PLL
, p_for_mclk_count_aud
, c_sw_pll
#endif
);
}
#endif
} // par
}
#ifndef USER_MAIN_DECLARATIONS
#define USER_MAIN_DECLARATIONS
#endif
#ifndef USER_MAIN_CORES
#define USER_MAIN_CORES
#endif
//extern unsafe client interface i2c_master_if i_i2c_client;
//extern unsafe client interface i2c_master_if i_i2c_client_t0;
extern void dsp_core0(void);
extern void board_setup();
extern void dsp_main (chanend c_data);
extern void SetEqDataChan (chanend c);
extern void SetEx3dHidChan (chanend c);
extern int dsp_worker_tile(chanend c_dsp_to_ex3d, int worker_id);
//extern int dsp_worker_tile_1(chanend c_dsp_to_ex3d, int worker_id);
extern void ex3d_task();
extern void hid_button_task(chanend cc_mic_level, chanend c_hid, chanend c_hidSendData, chanend c_uac_vol, chanend c_ex3d_hid_cmd);
#if HID_DFU_EN
extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx, streaming chanend c_dfu_rx);
#else
extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx);
#endif
extern void dnr_dsp_proc_task(void);
extern unsafe chanend uc_dsp_to_ex3d[DSP_WORKER_COUNT];
extern unsafe chanend uc_dsp_to_dnr_t1;
extern unsafe chanend uc_key_to_ubm_t0;
extern unsafe chanend uc_audiohw;
#if HID_DFU_EN
extern unsafe streaming chanend uc_dfu;
#endif
extern void key_sender(chanend c_key);
extern void key_receiver(chanend c_key);
extern void mute_handler();
/* Main for USB Audio Applications */
int main()
{
#if !XUA_USB_EN
#define c_mix_out null
#else
chan c_mix_out;
#endif
#ifdef MIDI
chan c_midi;
#endif
#ifdef IAP
chan c_iap;
#ifdef IAP_EA_NATIVE_TRANS
chan c_ea_data;
#endif
#endif
#if (MIXER)
chan c_mix_ctl;
#endif
#if (XUA_SPDIF_RX_EN)
streaming chan c_spdif_rx;
#else
#define c_spdif_rx null
#endif
#if (XUA_ADAT_RX_EN)
streaming chan c_adat_rx;
#else
#define c_adat_rx null
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
chan c_spdif_tx;
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
chan c_clk_ctl;
chan c_clk_int;
#else
#define c_clk_int null
#define c_clk_ctl null
#endif
#if (XUA_DFU_EN == 1)
interface i_dfu dfuInterface;
#else
#define dfuInterface null
#endif
#if (XUA_NUM_PDM_MICS > 0)
chan c_pdm_pcm;
#endif
#if (((XUA_SYNCMODE == XUA_SYNCMODE_SYNC && !XUA_USE_SW_PLL) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) )
interface pll_ref_if i_pll_ref;
#endif
#if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
chan c_sw_pll;
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
chan c_audio_rate_change; /* Notification of new mclk freq to ep_buffer */
#endif
chan c_sof;
chan c_xud_out[ENDPOINT_COUNT_OUT]; /* Endpoint channels for XUD */
chan c_xud_in[ENDPOINT_COUNT_IN];
/* Used to communicate controls/setting from XUA_Endpoint0() to the Audio/Buffering sub-system */
chan c_aud_ctl;
#if (!MIXER)
#define c_mix_ctl null
#endif
#ifdef IAP_EA_NATIVE_TRANS
chan c_EANativeTransport_ctrl;
#else
#define c_EANativeTransport_ctrl null
#endif
//#if (HID_CONTROLS > 0)
// chan c_hid;
//#endif
USER_MAIN_DECLARATIONS
chan c_dsp_to_ex3d[DSP_WORKER_COUNT];
chan cc_mic_level;
chan c_audiohw;
#if HID_DFU_EN
streaming chan c_dfu;
#endif
chan c_key; chan c_hidSendData;
chan c_hidRcvData;
chan c_eq_data;
chan c_uac_vol;
chan c_ex3d_hid_cmd;
par
{
USER_MAIN_CORES
on tile[1] : {
par {
unsafe {
uc_audiohw = (chanend)c_audiohw;
#if EQ_EN == 1 && USE_EX3D == 0
SetEqDataChan(c_eq_data);
#endif
hid_button_task(cc_mic_level, c_hidRcvData, c_hidSendData, c_uac_vol, c_ex3d_hid_cmd);
}
#if USE_EX3D == 1
par(int i = 0; i < DSP_WORKER_COUNT; i++)
dsp_worker_tile(c_dsp_to_ex3d[i], i);
unsafe {
SetEqDataChan(c_eq_data);
delay_milliseconds(200);
key_sender(c_key);
for (int i = 0; i < DSP_WORKER_COUNT; i++)
uc_dsp_to_ex3d[i] = (chanend)c_dsp_to_ex3d[i];
ex3d_task();
}
#endif
}
}
on tile[1]: mute_handler();
on tile[0] : {
par {
{
#if USE_EX3D == 1
unsafe { key_receiver(c_key); }
#endif
AudioHwRemote(c_hidSendData, cc_mic_level, c_uac_vol, c_audiohw
#if HID_DFU_EN
, c_dfu
#endif
);
}
}
}
#if EQ_EN == 1
on tile[0] : {
{
#if HID_DFU_EN
unsafe {
uc_dfu = (streaming chanend)c_dfu;
}
#endif
dsp_core0();
}
}
on tile[0] : { dsp_main(c_eq_data); }
#endif
#if DNR_ENABLE == 1
on tile[0] : { dnr_dsp_proc_task(); }
#endif
#if (((XUA_SYNCMODE == XUA_SYNCMODE_SYNC && !XUA_USE_SW_PLL) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN))
on tile[PLL_REF_TILE]: PllRefPinTask(i_pll_ref, p_pll_ref);
#endif
on tile[XUD_TILE]:
par
{
#if XUA_USB_EN
#if ((XUD_TILE == 0) && (XUA_DFU_EN == 1))
/* Check if USB is on the flash tile (tile 0) */
/* Expect to be distrbuted into XUA_Endpoint0() */
[[distribute]]
DFUHandler(dfuInterface, null);
#endif
/* Core USB task, buffering, USB etc */
{
#ifdef XUD_PRIORITY_HIGH
set_core_high_priority_on();
#endif
/* Run UAC2.0 at high-speed, UAC1.0 at full-speed */
unsigned usbSpeed = (AUDIO_CLASS == 2) ? XUD_SPEED_HS : XUD_SPEED_FS;
unsigned xudPwrCfg = (XUA_POWERMODE == XUA_POWERMODE_SELF) ? XUD_PWR_SELF : XUD_PWR_BUS;
/* USB interface core */
XUD_Main(c_xud_out, ENDPOINT_COUNT_OUT, c_xud_in, ENDPOINT_COUNT_IN,
c_sof, epTypeTableOut, epTypeTableIn, usbSpeed, xudPwrCfg);
}
#if (NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0) || XUA_HID_ENABLED || defined(MIDI)
/* Core USB audio task, buffering, USB etc */
{
unsigned x;
thread_speed();
/* Attach mclk count port to mclk clock-block (for feedback) */
//set_port_clock(p_for_mclk_count, clk_audio_mclk);
#if(AUDIO_IO_TILE != XUD_TILE)
set_clock_src(clk_audio_mclk_usb, p_mclk_in_usb);
set_port_clock(p_for_mclk_count, clk_audio_mclk_usb);
start_clock(clk_audio_mclk_usb);
#else
/* Clock port from same clock-block as I2S */
/* TODO remove asm() */
asm("ldw %0, dp[clk_audio_mclk]":"=r"(x));
asm("setclk res[%0], %1"::"r"(p_for_mclk_count), "r"(x));
#endif
/* Endpoint & audio buffering cores - buffers all EP's other than 0 */
XUA_Buffer(
#if (NUM_USB_CHAN_OUT > 0)
c_xud_out[ENDPOINT_NUMBER_OUT_AUDIO], /* Audio Out*/
#endif
#if (NUM_USB_CHAN_IN > 0)
c_xud_in[ENDPOINT_NUMBER_IN_AUDIO], /* Audio In */
#endif
#if (NUM_USB_CHAN_OUT > 0) && ((NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP))
c_xud_in[ENDPOINT_NUMBER_IN_FEEDBACK], /* Audio FB */
#endif
#ifdef MIDI
c_xud_out[ENDPOINT_NUMBER_OUT_MIDI], /* MIDI Out */ // 2
c_xud_in[ENDPOINT_NUMBER_IN_MIDI], /* MIDI In */ // 4
c_midi,
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
/* Audio Interrupt - only used for interrupts on external clock change */
c_xud_in[ENDPOINT_NUMBER_IN_INTERRUPT],
c_clk_int,
#endif
c_sof, c_aud_ctl, p_for_mclk_count
#if (XUA_HID_ENABLED)
, c_xud_in[ENDPOINT_NUMBER_IN_HID]
#endif
, c_mix_out
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, c_audio_rate_change
#if (!XUA_USE_SW_PLL)
, i_pll_ref
#else
, c_sw_pll
#endif
#endif
);
//:
}
#endif
/* Endpoint 0 Core */
{
thread_speed();
#if (USE_EX3D == 1) && (HID_CONTROLS > 0)
SetEx3dHidChan(c_ex3d_hid_cmd);
XUA_Endpoint0( c_xud_out[0], c_xud_in[0], c_hidRcvData, c_aud_ctl, c_mix_ctl, c_clk_ctl, c_EANativeTransport_ctrl, dfuInterface VENDOR_REQUESTS_PARAMS_);
#else
XUA_Endpoint0( c_xud_out[0], c_xud_in[0], c_aud_ctl, c_mix_ctl, c_clk_ctl, c_EANativeTransport_ctrl, dfuInterface VENDOR_REQUESTS_PARAMS_);
#endif
}
#endif /* XUA_USB_EN */
}
#if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
on tile[AUDIO_IO_TILE]: sw_pll_task(c_sw_pll);
#endif
on tile[AUDIO_IO_TILE]:
{
/* Audio I/O task, includes mixing etc */
usb_audio_io(
#if (NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0)
/* Connect audio system to XUA_Buffer(); */
c_mix_out
#else
/* Connect to XUA_Endpoint0() */
c_aud_ctl
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
, c_spdif_tx
#endif
#if (MIXER)
, c_mix_ctl
#endif
, c_spdif_rx, c_adat_rx, c_clk_ctl, c_clk_int
#if (XUD_TILE != 0) && (AUDIO_IO_TILE == 0) && (XUA_DFU_EN == 1)
, dfuInterface
#endif
#if (XUA_NUM_PDM_MICS > 0)
, c_pdm_pcm
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, i_pll_ref
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, c_audio_rate_change
#endif
#if ((XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
, p_for_mclk_count_audio
, c_sw_pll
#endif
);
}
//:
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
on tile[SPDIF_TX_TILE]:
{
thread_speed();
SpdifTxWrapper(c_spdif_tx);
}
#endif
#if defined(MIDI) && defined(IAP) && (IAP_TILE == MIDI_TILE)
/* MIDI and IAP share a core */
on tile[IAP_TILE]:
{
thread_speed();
usb_midi(p_midi_rx, p_midi_tx, clk_midi, c_midi, 0, c_iap, null, null, null);
}
#else
#if defined(MIDI)
/* MIDI core */
on tile[MIDI_TILE]:
{
thread_speed();
usb_midi(p_midi_rx, p_midi_tx, clk_midi, c_midi, 0);
}
#endif
#if defined(IAP)
on tile[IAP_TILE]:
{
thread_speed();
iAP(c_iap, null, null, null);
}
#endif
#endif
#if (XUA_SPDIF_RX_EN)
on tile[XUD_TILE]:
{
thread_speed();
spdif_rx(c_spdif_rx, p_spdif_rx, clk_spd_rx, 192000);
}
#endif
#if (XUA_ADAT_RX_EN)
on stdcore[XUD_TILE] :
{
set_thread_fast_mode_on();
while (1)
{
adatReceiver48000(p_adat_rx, c_adat_rx);
adatReceiver44100(p_adat_rx, c_adat_rx);
}
}
#endif
#if XUA_USB_EN
#if (XUD_TILE != 0) && (AUDIO_IO_TILE != 0) && (XUA_DFU_EN == 1)
/* Run flash code on its own - hope it gets combined */
//#warning Running DFU flash code on its own
on stdcore[0]: DFUHandler(dfuInterface, null);
#endif
#endif
#if (XUA_NUM_PDM_MICS > 0)
/* PDM Mics running on a separate to AudioHub */
on stdcore[PDM_TILE]:
{
mic_array_task(c_mic_pcm);
}
#endif /*XUA_NUM_PDM_MICS > 0*/
}
return 0;
}
#endif

View File

@@ -0,0 +1,844 @@
// Copyright 2012-2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include "xua.h" /* Device specific defines */
#ifdef EXCLUDE_USB_AUDIO_MAIN
/**
* @file main.xc
* @brief Top level for XMOS USB 2.0 Audio 2.0 Reference Designs.
* @author Ross Owen, XMOS Semiconductor Ltd
*/
#include <syscall.h>
#include <platform.h>
#include <xs1.h>
#include <xclib.h>
#include <print.h>
#ifdef XSCOPE
#include <xscope.h>
#endif
#if XUA_USB_EN
#include "xud_device.h" /* XMOS USB Device Layer defines and functions */
#include "xua_endpoint0.h"
#endif
#include "uac_hwresources.h"
#ifdef IAP
#include "i2c_shared.h"
#include "iap.h"
#endif
#if (XUA_SPDIF_RX_EN || XUA_SPDIF_TX_EN)
#include "spdif.h" /* From lib_spdif */
#endif
#if (XUA_ADAT_RX_EN)
#include "adat_rx.h"
#endif
#if (XUA_NUM_PDM_MICS > 0)
#include "xua_pdm_mic.h"
#endif
#if (XUA_DFU_EN == 1)
[[distributable]]
void DFUHandler(server interface i_dfu i, chanend ?c_user_cmd);
#endif
/* Audio I/O - Port declarations */
#if I2S_WIRES_DAC > 0
on tile[AUDIO_IO_TILE] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] =
{PORT_I2S_DAC0,
#endif
#if I2S_WIRES_DAC > 1
PORT_I2S_DAC1,
#endif
#if I2S_WIRES_DAC > 2
PORT_I2S_DAC2,
#endif
#if I2S_WIRES_DAC > 3
PORT_I2S_DAC3,
#endif
#if I2S_WIRES_DAC > 4
PORT_I2S_DAC4,
#endif
#if I2S_WIRES_DAC > 5
PORT_I2S_DAC5,
#endif
#if I2S_WIRES_DAC > 6
PORT_I2S_DAC6,
#endif
#if I2S_WIRES_DAC > 7
#error I2S_WIRES_DAC value is too large!
#endif
#if I2S_WIRES_DAC > 0
};
#else
#define p_i2s_dac null
#endif
#if I2S_WIRES_ADC > 0
on tile[AUDIO_IO_TILE] : buffered in port:32 p_i2s_adc[I2S_WIRES_ADC] =
{PORT_I2S_ADC0,
#endif
#if I2S_WIRES_ADC > 1
PORT_I2S_ADC1,
#endif
#if I2S_WIRES_ADC > 2
PORT_I2S_ADC2,
#endif
#if I2S_WIRES_ADC > 3
PORT_I2S_ADC3,
#endif
#if I2S_WIRES_ADC > 4
PORT_I2S_ADC4,
#endif
#if I2S_WIRES_ADC > 5
PORT_I2S_ADC5,
#endif
#if I2S_WIRES_ADC > 6
PORT_I2S_ADC6,
#endif
#if I2S_WIRES_ADC > 7
#error I2S_WIRES_ADC value is too large!
#endif
#if I2S_WIRES_ADC > 0
};
#else
#define p_i2s_adc null
#endif
#if CODEC_MASTER
on tile[AUDIO_IO_TILE] : buffered in port:32 p_lrclk = PORT_I2S_LRCLK;
on tile[AUDIO_IO_TILE] : buffered in port:32 p_bclk = PORT_I2S_BCLK;
#else
on tile[AUDIO_IO_TILE] : buffered out port:32 p_lrclk = PORT_I2S_LRCLK;
on tile[AUDIO_IO_TILE] : buffered out port:32 p_bclk = PORT_I2S_BCLK;
#endif
#if (!CODEC_MASTER) || XUA_SPDIF_TX_EN || XUA_ADAT_TX_EN || ((AUDIO_IO_TILE == XUD_TILE) && XUA_USB_EN)
/* Audio master clock input */
on tile[AUDIO_IO_TILE] : in port p_mclk_in = PORT_MCLK_IN;
#else
#define p_mclk_in null
#endif
#if (AUDIO_IO_TILE != XUD_TILE) && XUA_USB_EN
/* If audio I/O and USB running on different tiles we need a separate port for
* the master clock input (to use for USB async feedback calculation) */
on tile[XUD_TILE] : in port p_mclk_in_usb = PORT_MCLK_IN_USB;
#endif
#if XUA_USB_EN
on tile[XUD_TILE] : in port p_for_mclk_count = PORT_MCLK_COUNT;
#endif
#if (XUA_SPDIF_TX_EN)
on tile[SPDIF_TX_TILE] : buffered out port:32 p_spdif_tx = PORT_SPDIF_OUT;
#endif
#if (XUA_ADAT_TX_EN)
on stdcore[AUDIO_IO_TILE] : buffered out port:32 p_adat_tx = PORT_ADAT_OUT;
#endif
#if (XUA_ADAT_RX_EN)
on stdcore[XUD_TILE] : buffered in port:32 p_adat_rx = PORT_ADAT_IN;
#endif
#if (XUA_SPDIF_RX_EN)
on tile[XUD_TILE] : in port p_spdif_rx = PORT_SPDIF_IN;
#endif
#if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN) || (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
/* Reference to external clock multiplier */
on tile[PLL_REF_TILE] : out port p_pll_ref = PORT_PLL_REF;
#ifdef __XS3A__
on tile[AUDIO_IO_TILE] : port p_for_mclk_count_audio = PORT_MCLK_COUNT_2;
#else /* __XS3A__ */
#define p_for_mclk_count_audio null
#endif /* __XS3A__ */
#endif
#ifdef MIDI
on tile[MIDI_TILE] : port p_midi_tx = PORT_MIDI_OUT;
#if(MIDI_RX_PORT_WIDTH == 4)
on tile[MIDI_TILE] : buffered in port:4 p_midi_rx = PORT_MIDI_IN;
#elif(MIDI_RX_PORT_WIDTH == 1)
on tile[MIDI_TILE] : buffered in port:1 p_midi_rx = PORT_MIDI_IN;
#endif
#endif
#ifdef MIDI
on tile[MIDI_TILE] : clock clk_midi = CLKBLK_MIDI;
#endif
#if (XUA_SPDIF_TX_EN || XUA_ADAT_TX_EN)
on tile[SPDIF_TX_TILE] : clock clk_mst_spd = CLKBLK_SPDIF_TX;
#endif
#if (XUA_SPDIF_RX_EN)
on tile[XUD_TILE] : clock clk_spd_rx = CLKBLK_SPDIF_RX;
#endif
on tile[AUDIO_IO_TILE] : clock clk_audio_mclk = CLKBLK_MCLK; /* Master clock */
#if (AUDIO_IO_TILE != XUD_TILE) && XUA_USB_EN
/* Separate clock/port for USB feedback calculation */
on tile[XUD_TILE] : clock clk_audio_mclk_usb = CLKBLK_MCLK; /* Master clock */
#endif
on tile[AUDIO_IO_TILE] : clock clk_audio_bclk = CLKBLK_I2S_BIT; /* Bit clock */
#ifdef IAP
/* I2C ports - in a struct for use with module_i2c_shared & module_i2c_simple/module_i2c_single_port */
#ifdef PORT_I2C
on tile [IAP_TILE] : struct r_i2c r_i2c = {PORT_I2C};
#else
on tile [IAP_TILE] : struct r_i2c r_i2c = {PORT_I2C_SCL, PORT_I2C_SDA};
#endif
#endif
#if XUA_USB_EN
/* Endpoint type tables for XUD */
XUD_EpType epTypeTableOut[ENDPOINT_COUNT_OUT] = { XUD_EPTYPE_CTL | XUD_STATUS_ENABLE,
#if (NUM_USB_CHAN_IN > 0)
XUD_EPTYPE_ISO, /* Audio */
#endif
#ifdef MIDI
XUD_EPTYPE_BUL, /* MIDI */
#endif
#if HID_OUT_REQUIRED
XUD_EPTYPE_INT,
#endif
#ifdef IAP
XUD_EPTYPE_BUL, /* iAP */
#ifdef IAP_EA_NATIVE_TRANS
XUD_EPTYPE_BUL, /* EA Native Transport */
#endif
#endif
};
XUD_EpType epTypeTableIn[ENDPOINT_COUNT_IN] = { XUD_EPTYPE_CTL | XUD_STATUS_ENABLE,
#if (NUM_USB_CHAN_IN > 0)
XUD_EPTYPE_ISO,
#endif
#if (NUM_USB_CHAN_OUT > 0) && ((NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP))
XUD_EPTYPE_ISO, /* Async feedback endpoint */
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
XUD_EPTYPE_INT,
#endif
#ifdef MIDI
XUD_EPTYPE_BUL,
#endif
#if XUA_OR_STATIC_HID_ENABLED
XUD_EPTYPE_INT,
#endif
#ifdef IAP
XUD_EPTYPE_BUL | XUD_STATUS_ENABLE,
#ifdef IAP_INT_EP
XUD_EPTYPE_BUL | XUD_STATUS_ENABLE,
#endif
#ifdef IAP_EA_NATIVE_TRANS
XUD_EPTYPE_BUL | XUD_STATUS_ENABLE,
#endif
#endif
};
#endif /* XUA_USB_EN */
void thread_speed()
{
#ifdef FAST_MODE
#warning Building with fast mode enabled
set_thread_fast_mode_on();
#else
set_thread_fast_mode_off();
#endif
}
#ifdef XSCOPE
void xscope_user_init()
{
xscope_register(0, 0, "", 0, "");
xscope_config_io(XSCOPE_IO_BASIC);
}
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
void SpdifTxWrapper(chanend c_spdif_tx)
{
unsigned portId;
//configure_clock_src(clk, p_mclk);
// TODO could share clock block here..
// NOTE, Assuming SPDIF tile == USB tile here..
asm("ldw %0, dp[p_mclk_in_usb]":"=r"(portId));
asm("setclk res[%0], %1"::"r"(clk_mst_spd), "r"(portId));
configure_out_port_no_ready(p_spdif_tx, clk_mst_spd, 0);
set_clock_fall_delay(clk_mst_spd, 7);
start_clock(clk_mst_spd);
while(1)
{
spdif_tx(p_spdif_tx, c_spdif_tx);
}
}
#endif
void usb_audio_io(chanend ?c_aud_in,
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
chanend c_spdif_tx,
#endif
#if (MIXER)
chanend c_mix_ctl,
#endif
streaming chanend ?c_spdif_rx,
streaming chanend ?c_adat_rx,
chanend ?c_clk_ctl,
chanend ?c_clk_int
#if (XUD_TILE != 0) && (AUDIO_IO_TILE == 0) && (XUA_DFU_EN == 1)
, server interface i_dfu ?dfuInterface
#endif
#if (XUA_NUM_PDM_MICS > 0)
, chanend c_pdm_pcm
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, client interface pll_ref_if i_pll_ref
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, chanend c_audio_rate_change
#endif
#if ((XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
, port p_for_mclk_count_aud
, chanend c_sw_pll
#endif
)
{
#if (MIXER)
chan c_mix_out;
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
chan c_dig_rx;
chan c_audio_rate_change; /* Notification of new mclk freq to clockgen and synch */
#if XUA_USE_SW_PLL
/* Connect p_for_mclk_count_aud to clk_audio_mclk so we can count mclks/timestamp in digital rx*/
unsigned x = 0;
asm("ldw %0, dp[clk_audio_mclk]":"=r"(x));
asm("setclk res[%0], %1"::"r"(p_for_mclk_count_aud), "r"(x));
#endif /* XUA_USE_SW_PLL */
#endif /* (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) */
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE == AUDIO_IO_TILE)
chan c_spdif_tx;
/* Setup S/PDIF tx port - note this is done before par since sharing clock-block/port */
spdif_tx_port_config(p_spdif_tx, clk_audio_mclk, p_mclk_in, 7);
#endif
par
{
#if (MIXER && XUA_USB_EN)
/* Mixer cores(s) */
{
thread_speed();
mixer(c_aud_in, c_mix_out, c_mix_ctl);
}
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE == AUDIO_IO_TILE)
while(1)
{
spdif_tx(p_spdif_tx, c_spdif_tx);
}
#endif
/* Audio I/O core (pars additional S/PDIF TX Core) */
{
thread_speed();
#if (MIXER)
#define AUDIO_CHANNEL c_mix_out
#else
#define AUDIO_CHANNEL c_aud_in
#endif
XUA_AudioHub(AUDIO_CHANNEL, clk_audio_mclk, clk_audio_bclk, p_mclk_in, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc
#if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE)
, c_spdif_tx
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, c_dig_rx
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, c_audio_rate_change
#endif
#if (XUD_TILE != 0) && (AUDIO_IO_TILE == 0) && (XUA_DFU_EN == 1)
, dfuInterface
#endif
#if (XUA_NUM_PDM_MICS > 0)
, c_pdm_pcm
#endif
);
}
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
{
/* ClockGen must currently run on same tile as AudioHub due to shared memory buffer
* However, due to the use of an interface the pll reference signal port can be on another tile
*/
thread_speed();
clockGen( c_spdif_rx,
c_adat_rx,
i_pll_ref,
c_dig_rx,
c_clk_ctl,
c_clk_int,
c_audio_rate_change
#if XUA_USE_SW_PLL
, p_for_mclk_count_aud
, c_sw_pll
#endif
);
}
#endif
} // par
}
#ifndef USER_MAIN_DECLARATIONS
#define USER_MAIN_DECLARATIONS
#endif
#ifndef USER_MAIN_CORES
#define USER_MAIN_CORES
#endif
//extern unsafe client interface i2c_master_if i_i2c_client;
//extern unsafe client interface i2c_master_if i_i2c_client_t0;
extern void dsp_core0(void);
extern void board_setup();
extern void dsp_main (streaming chanend c_data);
extern void SetEqDataChan (streaming chanend c);
extern void SetUbmInitChan (streaming chanend c);
extern void UserBufferForwardingTask(streaming chanend c_dsp, streaming chanend c_init);
extern void SetEx3dHidChan (chanend c);
extern int dsp_worker_tile(chanend c_dsp_to_ex3d, int worker_id);
//extern int dsp_worker_tile_1(chanend c_dsp_to_ex3d, int worker_id);
extern void ex3d_task();
extern void hid_button_task(chanend cc_mic_level, chanend c_hid, chanend c_hidSendData, chanend c_uac_vol, chanend c_ex3d_hid_cmd);
#if HID_DFU_EN
extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx, streaming chanend c_dfu_rx, chanend c_mic_det);
#else
extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx, chanend c_mic_det);
#endif
extern void dnr_dsp_proc_task(void);
extern unsafe chanend uc_dsp_to_ex3d[DSP_WORKER_COUNT];
extern unsafe chanend uc_dsp_to_dnr_t1;
extern unsafe chanend uc_key_to_ubm_t0;
extern unsafe chanend uc_audiohw;
#if HID_DFU_EN
extern unsafe streaming chanend uc_dfu;
#endif
extern void key_sender(chanend c_key);
extern void key_receiver(chanend c_key);
extern void mute_handler(chanend c_mic_det);
/* Main for USB Audio Applications */
int main()
{
#if !XUA_USB_EN
#define c_mix_out null
#else
chan c_mix_out;
#endif
#ifdef MIDI
chan c_midi;
#endif
#ifdef IAP
chan c_iap;
#ifdef IAP_EA_NATIVE_TRANS
chan c_ea_data;
#endif
#endif
#if (MIXER)
chan c_mix_ctl;
#endif
#if (XUA_SPDIF_RX_EN)
streaming chan c_spdif_rx;
#else
#define c_spdif_rx null
#endif
#if (XUA_ADAT_RX_EN)
streaming chan c_adat_rx;
#else
#define c_adat_rx null
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
chan c_spdif_tx;
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
chan c_clk_ctl;
chan c_clk_int;
#else
#define c_clk_int null
#define c_clk_ctl null
#endif
#if (XUA_DFU_EN == 1)
interface i_dfu dfuInterface;
#else
#define dfuInterface null
#endif
#if (XUA_NUM_PDM_MICS > 0)
chan c_pdm_pcm;
#endif
#if (((XUA_SYNCMODE == XUA_SYNCMODE_SYNC && !XUA_USE_SW_PLL) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) )
interface pll_ref_if i_pll_ref;
#endif
#if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
chan c_sw_pll;
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
chan c_audio_rate_change; /* Notification of new mclk freq to ep_buffer */
#endif
chan c_sof;
chan c_xud_out[ENDPOINT_COUNT_OUT]; /* Endpoint channels for XUD */
chan c_xud_in[ENDPOINT_COUNT_IN];
/* Used to communicate controls/setting from XUA_Endpoint0() to the Audio/Buffering sub-system */
chan c_aud_ctl;
#if (!MIXER)
#define c_mix_ctl null
#endif
#ifdef IAP_EA_NATIVE_TRANS
chan c_EANativeTransport_ctrl;
#else
#define c_EANativeTransport_ctrl null
#endif
//#if (HID_CONTROLS > 0)
// chan c_hid;
//#endif
USER_MAIN_DECLARATIONS
chan c_dsp_to_ex3d[DSP_WORKER_COUNT];
chan cc_mic_level;
chan c_audiohw;
#if HID_DFU_EN
streaming chan c_dfu;
#endif
chan c_key; chan c_hidSendData;
chan c_hidRcvData;
streaming chan c_eq_data;
streaming chan c_ubm_init;
chan c_uac_vol;
chan c_ex3d_hid_cmd;
chan c_mic_det;
par
{
USER_MAIN_CORES
on tile[1] : {
par {
// Forwarder Task on its own core
UserBufferForwardingTask(c_eq_data, c_ubm_init);
// HID & Control sequence on its own core
unsafe {
uc_audiohw = (chanend)c_audiohw;
SetUbmInitChan(c_ubm_init);
hid_button_task(cc_mic_level, c_hidRcvData, c_hidSendData, c_uac_vol, c_ex3d_hid_cmd);
}
#if USE_EX3D == 1
// Workers on their own cores
par(int i = 0; i < DSP_WORKER_COUNT; i++)
dsp_worker_tile(c_dsp_to_ex3d[i], i);
// EX3D Task sequence on its own core
unsafe {
delay_milliseconds(200);
key_sender(c_key);
for (int i = 0; i < DSP_WORKER_COUNT; i++)
uc_dsp_to_ex3d[i] = (chanend)c_dsp_to_ex3d[i];
ex3d_task();
}
#endif
}
}
on tile[1]: mute_handler(c_mic_det);
on tile[0] : {
par {
{
#if USE_EX3D == 1
unsafe { key_receiver(c_key); }
#endif
AudioHwRemote(c_hidSendData, cc_mic_level, c_uac_vol, c_audiohw
#if HID_DFU_EN
, c_dfu
#endif
, c_mic_det
);
}
}
}
#if EQ_EN == 1
on tile[0] : {
{
#if HID_DFU_EN
unsafe {
uc_dfu = (streaming chanend)c_dfu;
}
#endif
dsp_core0();
}
}
on tile[0] : { dsp_main(c_eq_data); }
#endif
#if DNR_ENABLE == 1
on tile[0] : { dnr_dsp_proc_task(); }
#endif
#if (((XUA_SYNCMODE == XUA_SYNCMODE_SYNC && !XUA_USE_SW_PLL) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN))
on tile[PLL_REF_TILE]: PllRefPinTask(i_pll_ref, p_pll_ref);
#endif
on tile[XUD_TILE]:
par
{
#if XUA_USB_EN
#if ((XUD_TILE == 0) && (XUA_DFU_EN == 1))
/* Check if USB is on the flash tile (tile 0) */
/* Expect to be distrbuted into XUA_Endpoint0() */
[[distribute]]
DFUHandler(dfuInterface, null);
#endif
/* Core USB task, buffering, USB etc */
{
#ifdef XUD_PRIORITY_HIGH
set_core_high_priority_on();
#endif
/* Run UAC2.0 at high-speed, UAC1.0 at full-speed */
unsigned usbSpeed = (AUDIO_CLASS == 2) ? XUD_SPEED_HS : XUD_SPEED_FS;
unsigned xudPwrCfg = (XUA_POWERMODE == XUA_POWERMODE_SELF) ? XUD_PWR_SELF : XUD_PWR_BUS;
/* USB interface core */
XUD_Main(c_xud_out, ENDPOINT_COUNT_OUT, c_xud_in, ENDPOINT_COUNT_IN,
c_sof, epTypeTableOut, epTypeTableIn, usbSpeed, xudPwrCfg);
}
#if (NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0) || XUA_HID_ENABLED || defined(MIDI)
/* Core USB audio task, buffering, USB etc */
{
unsigned x;
thread_speed();
/* Attach mclk count port to mclk clock-block (for feedback) */
//set_port_clock(p_for_mclk_count, clk_audio_mclk);
#if(AUDIO_IO_TILE != XUD_TILE)
set_clock_src(clk_audio_mclk_usb, p_mclk_in_usb);
set_port_clock(p_for_mclk_count, clk_audio_mclk_usb);
start_clock(clk_audio_mclk_usb);
#else
/* Clock port from same clock-block as I2S */
/* TODO remove asm() */
asm("ldw %0, dp[clk_audio_mclk]":"=r"(x));
asm("setclk res[%0], %1"::"r"(p_for_mclk_count), "r"(x));
#endif
/* Endpoint & audio buffering cores - buffers all EP's other than 0 */
XUA_Buffer(
#if (NUM_USB_CHAN_OUT > 0)
c_xud_out[ENDPOINT_NUMBER_OUT_AUDIO], /* Audio Out*/
#endif
#if (NUM_USB_CHAN_IN > 0)
c_xud_in[ENDPOINT_NUMBER_IN_AUDIO], /* Audio In */
#endif
#if (NUM_USB_CHAN_OUT > 0) && ((NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP))
c_xud_in[ENDPOINT_NUMBER_IN_FEEDBACK], /* Audio FB */
#endif
#ifdef MIDI
c_xud_out[ENDPOINT_NUMBER_OUT_MIDI], /* MIDI Out */ // 2
c_xud_in[ENDPOINT_NUMBER_IN_MIDI], /* MIDI In */ // 4
c_midi,
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
/* Audio Interrupt - only used for interrupts on external clock change */
c_xud_in[ENDPOINT_NUMBER_IN_INTERRUPT],
c_clk_int,
#endif
c_sof, c_aud_ctl, p_for_mclk_count
#if (XUA_HID_ENABLED)
, c_xud_in[ENDPOINT_NUMBER_IN_HID]
#endif
, c_mix_out
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, c_audio_rate_change
#if (!XUA_USE_SW_PLL)
, i_pll_ref
#else
, c_sw_pll
#endif
#endif
);
//:
}
#endif
/* Endpoint 0 Core */
{
thread_speed();
#if (USE_EX3D == 1) && (HID_CONTROLS > 0)
SetEx3dHidChan(c_ex3d_hid_cmd);
XUA_Endpoint0( c_xud_out[0], c_xud_in[0], c_hidRcvData, c_aud_ctl, c_mix_ctl, c_clk_ctl, c_EANativeTransport_ctrl, dfuInterface VENDOR_REQUESTS_PARAMS_);
#else
XUA_Endpoint0( c_xud_out[0], c_xud_in[0], c_aud_ctl, c_mix_ctl, c_clk_ctl, c_EANativeTransport_ctrl, dfuInterface VENDOR_REQUESTS_PARAMS_);
#endif
}
#endif /* XUA_USB_EN */
}
#if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
on tile[AUDIO_IO_TILE]: sw_pll_task(c_sw_pll);
#endif
on tile[AUDIO_IO_TILE]:
{
set_core_high_priority_on();
/* Audio I/O task, includes mixing etc */
usb_audio_io(
#if (NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0)
/* Connect audio system to XUA_Buffer(); */
c_mix_out
#else
/* Connect to XUA_Endpoint0() */
c_aud_ctl
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
, c_spdif_tx
#endif
#if (MIXER)
, c_mix_ctl
#endif
, c_spdif_rx, c_adat_rx, c_clk_ctl, c_clk_int
#if (XUD_TILE != 0) && (AUDIO_IO_TILE == 0) && (XUA_DFU_EN == 1)
, dfuInterface
#endif
#if (XUA_NUM_PDM_MICS > 0)
, c_pdm_pcm
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, i_pll_ref
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, c_audio_rate_change
#endif
#if ((XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
, p_for_mclk_count_audio
, c_sw_pll
#endif
);
}
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
on tile[SPDIF_TX_TILE]:
{
thread_speed();
SpdifTxWrapper(c_spdif_tx);
}
#endif
#if defined(MIDI) && defined(IAP) && (IAP_TILE == MIDI_TILE)
/* MIDI and IAP share a core */
on tile[IAP_TILE]:
{
thread_speed();
usb_midi(p_midi_rx, p_midi_tx, clk_midi, c_midi, 0, c_iap, null, null, null);
}
#else
#if defined(MIDI)
/* MIDI core */
on tile[MIDI_TILE]:
{
thread_speed();
usb_midi(p_midi_rx, p_midi_tx, clk_midi, c_midi, 0);
}
#endif
#if defined(IAP)
on tile[IAP_TILE]:
{
thread_speed();
iAP(c_iap, null, null, null);
}
#endif
#endif
#if (XUA_SPDIF_RX_EN)
on tile[XUD_TILE]:
{
thread_speed();
spdif_rx(c_spdif_rx, p_spdif_rx, clk_spd_rx, 192000);
}
#endif
#if (XUA_ADAT_RX_EN)
on stdcore[XUD_TILE] :
{
set_thread_fast_mode_on();
while (1)
{
adatReceiver48000(p_adat_rx, c_adat_rx);
adatReceiver44100(p_adat_rx, c_adat_rx);
}
}
#endif
#if XUA_USB_EN
#if (XUD_TILE != 0) && (AUDIO_IO_TILE != 0) && (XUA_DFU_EN == 1)
/* Run flash code on its own - hope it gets combined */
//#warning Running DFU flash code on its own
on stdcore[0]: DFUHandler(dfuInterface, null);
#endif
#endif
#if (XUA_NUM_PDM_MICS > 0)
/* PDM Mics running on a separate to AudioHub */
on stdcore[PDM_TILE]:
{
mic_array_task(c_mic_pcm);
}
#endif /*XUA_NUM_PDM_MICS > 0*/
}
return 0;
}
#endif

View File

@@ -0,0 +1,846 @@
// Copyright 2012-2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#include "xua.h" /* Device specific defines */
#ifdef EXCLUDE_USB_AUDIO_MAIN
/**
* @file main.xc
* @brief Top level for XMOS USB 2.0 Audio 2.0 Reference Designs.
* @author Ross Owen, XMOS Semiconductor Ltd
*/
#include <syscall.h>
#include <platform.h>
#include <xs1.h>
#include <xclib.h>
#include <print.h>
#ifdef XSCOPE
#include <xscope.h>
#endif
#if XUA_USB_EN
#include "xud_device.h" /* XMOS USB Device Layer defines and functions */
#include "xua_endpoint0.h"
#endif
#include "uac_hwresources.h"
#ifdef IAP
#include "i2c_shared.h"
#include "iap.h"
#endif
#if (XUA_SPDIF_RX_EN || XUA_SPDIF_TX_EN)
#include "spdif.h" /* From lib_spdif */
#endif
#if (XUA_ADAT_RX_EN)
#include "adat_rx.h"
#endif
#if (XUA_NUM_PDM_MICS > 0)
#include "xua_pdm_mic.h"
#endif
#if (XUA_DFU_EN == 1)
[[distributable]]
void DFUHandler(server interface i_dfu i, chanend ?c_user_cmd);
#endif
/* Audio I/O - Port declarations */
#if I2S_WIRES_DAC > 0
on tile[AUDIO_IO_TILE] : buffered out port:32 p_i2s_dac[I2S_WIRES_DAC] =
{PORT_I2S_DAC0,
#endif
#if I2S_WIRES_DAC > 1
PORT_I2S_DAC1,
#endif
#if I2S_WIRES_DAC > 2
PORT_I2S_DAC2,
#endif
#if I2S_WIRES_DAC > 3
PORT_I2S_DAC3,
#endif
#if I2S_WIRES_DAC > 4
PORT_I2S_DAC4,
#endif
#if I2S_WIRES_DAC > 5
PORT_I2S_DAC5,
#endif
#if I2S_WIRES_DAC > 6
PORT_I2S_DAC6,
#endif
#if I2S_WIRES_DAC > 7
#error I2S_WIRES_DAC value is too large!
#endif
#if I2S_WIRES_DAC > 0
};
#else
#define p_i2s_dac null
#endif
#if I2S_WIRES_ADC > 0
on tile[AUDIO_IO_TILE] : buffered in port:32 p_i2s_adc[I2S_WIRES_ADC] =
{PORT_I2S_ADC0,
#endif
#if I2S_WIRES_ADC > 1
PORT_I2S_ADC1,
#endif
#if I2S_WIRES_ADC > 2
PORT_I2S_ADC2,
#endif
#if I2S_WIRES_ADC > 3
PORT_I2S_ADC3,
#endif
#if I2S_WIRES_ADC > 4
PORT_I2S_ADC4,
#endif
#if I2S_WIRES_ADC > 5
PORT_I2S_ADC5,
#endif
#if I2S_WIRES_ADC > 6
PORT_I2S_ADC6,
#endif
#if I2S_WIRES_ADC > 7
#error I2S_WIRES_ADC value is too large!
#endif
#if I2S_WIRES_ADC > 0
};
#else
#define p_i2s_adc null
#endif
#if CODEC_MASTER
on tile[AUDIO_IO_TILE] : buffered in port:32 p_lrclk = PORT_I2S_LRCLK;
on tile[AUDIO_IO_TILE] : buffered in port:32 p_bclk = PORT_I2S_BCLK;
#else
on tile[AUDIO_IO_TILE] : buffered out port:32 p_lrclk = PORT_I2S_LRCLK;
on tile[AUDIO_IO_TILE] : buffered out port:32 p_bclk = PORT_I2S_BCLK;
#endif
#if (!CODEC_MASTER) || XUA_SPDIF_TX_EN || XUA_ADAT_TX_EN || ((AUDIO_IO_TILE == XUD_TILE) && XUA_USB_EN)
/* Audio master clock input */
on tile[AUDIO_IO_TILE] : in port p_mclk_in = PORT_MCLK_IN;
#else
#define p_mclk_in null
#endif
#if (AUDIO_IO_TILE != XUD_TILE) && XUA_USB_EN
/* If audio I/O and USB running on different tiles we need a separate port for
* the master clock input (to use for USB async feedback calculation) */
on tile[XUD_TILE] : in port p_mclk_in_usb = PORT_MCLK_IN_USB;
#endif
#if XUA_USB_EN
on tile[XUD_TILE] : in port p_for_mclk_count = PORT_MCLK_COUNT;
#endif
#if (XUA_SPDIF_TX_EN)
on tile[SPDIF_TX_TILE] : buffered out port:32 p_spdif_tx = PORT_SPDIF_OUT;
#endif
#if (XUA_ADAT_TX_EN)
on stdcore[AUDIO_IO_TILE] : buffered out port:32 p_adat_tx = PORT_ADAT_OUT;
#endif
#if (XUA_ADAT_RX_EN)
on stdcore[XUD_TILE] : buffered in port:32 p_adat_rx = PORT_ADAT_IN;
#endif
#if (XUA_SPDIF_RX_EN)
on tile[XUD_TILE] : in port p_spdif_rx = PORT_SPDIF_IN;
#endif
#if (XUA_SPDIF_RX_EN) || (XUA_ADAT_RX_EN) || (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
/* Reference to external clock multiplier */
on tile[PLL_REF_TILE] : out port p_pll_ref = PORT_PLL_REF;
#ifdef __XS3A__
on tile[AUDIO_IO_TILE] : port p_for_mclk_count_audio = PORT_MCLK_COUNT_2;
#else /* __XS3A__ */
#define p_for_mclk_count_audio null
#endif /* __XS3A__ */
#endif
#ifdef MIDI
on tile[MIDI_TILE] : port p_midi_tx = PORT_MIDI_OUT;
#if(MIDI_RX_PORT_WIDTH == 4)
on tile[MIDI_TILE] : buffered in port:4 p_midi_rx = PORT_MIDI_IN;
#elif(MIDI_RX_PORT_WIDTH == 1)
on tile[MIDI_TILE] : buffered in port:1 p_midi_rx = PORT_MIDI_IN;
#endif
#endif
#ifdef MIDI
on tile[MIDI_TILE] : clock clk_midi = CLKBLK_MIDI;
#endif
#if (XUA_SPDIF_TX_EN || XUA_ADAT_TX_EN)
on tile[SPDIF_TX_TILE] : clock clk_mst_spd = CLKBLK_SPDIF_TX;
#endif
#if (XUA_SPDIF_RX_EN)
on tile[XUD_TILE] : clock clk_spd_rx = CLKBLK_SPDIF_RX;
#endif
on tile[AUDIO_IO_TILE] : clock clk_audio_mclk = CLKBLK_MCLK; /* Master clock */
#if (AUDIO_IO_TILE != XUD_TILE) && XUA_USB_EN
/* Separate clock/port for USB feedback calculation */
on tile[XUD_TILE] : clock clk_audio_mclk_usb = CLKBLK_MCLK; /* Master clock */
#endif
on tile[AUDIO_IO_TILE] : clock clk_audio_bclk = CLKBLK_I2S_BIT; /* Bit clock */
#ifdef IAP
/* I2C ports - in a struct for use with module_i2c_shared & module_i2c_simple/module_i2c_single_port */
#ifdef PORT_I2C
on tile [IAP_TILE] : struct r_i2c r_i2c = {PORT_I2C};
#else
on tile [IAP_TILE] : struct r_i2c r_i2c = {PORT_I2C_SCL, PORT_I2C_SDA};
#endif
#endif
#if XUA_USB_EN
/* Endpoint type tables for XUD */
XUD_EpType epTypeTableOut[ENDPOINT_COUNT_OUT] = { XUD_EPTYPE_CTL | XUD_STATUS_ENABLE,
#if (NUM_USB_CHAN_IN > 0)
XUD_EPTYPE_ISO, /* Audio */
#endif
#ifdef MIDI
XUD_EPTYPE_BUL, /* MIDI */
#endif
#if HID_OUT_REQUIRED
XUD_EPTYPE_INT,
#endif
#ifdef IAP
XUD_EPTYPE_BUL, /* iAP */
#ifdef IAP_EA_NATIVE_TRANS
XUD_EPTYPE_BUL, /* EA Native Transport */
#endif
#endif
};
XUD_EpType epTypeTableIn[ENDPOINT_COUNT_IN] = { XUD_EPTYPE_CTL | XUD_STATUS_ENABLE,
#if (NUM_USB_CHAN_IN > 0)
XUD_EPTYPE_ISO,
#endif
#if (NUM_USB_CHAN_OUT > 0) && ((NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP))
XUD_EPTYPE_ISO, /* Async feedback endpoint */
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
XUD_EPTYPE_INT,
#endif
#ifdef MIDI
XUD_EPTYPE_BUL,
#endif
#if XUA_OR_STATIC_HID_ENABLED
XUD_EPTYPE_INT,
#endif
#ifdef IAP
XUD_EPTYPE_BUL | XUD_STATUS_ENABLE,
#ifdef IAP_INT_EP
XUD_EPTYPE_BUL | XUD_STATUS_ENABLE,
#endif
#ifdef IAP_EA_NATIVE_TRANS
XUD_EPTYPE_BUL | XUD_STATUS_ENABLE,
#endif
#endif
};
#endif /* XUA_USB_EN */
void thread_speed()
{
#ifdef FAST_MODE
#warning Building with fast mode enabled
set_thread_fast_mode_on();
#else
set_thread_fast_mode_off();
#endif
}
#ifdef XSCOPE
void xscope_user_init()
{
xscope_register(0, 0, "", 0, "");
xscope_config_io(XSCOPE_IO_BASIC);
}
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
void SpdifTxWrapper(chanend c_spdif_tx)
{
unsigned portId;
//configure_clock_src(clk, p_mclk);
// TODO could share clock block here..
// NOTE, Assuming SPDIF tile == USB tile here..
asm("ldw %0, dp[p_mclk_in_usb]":"=r"(portId));
asm("setclk res[%0], %1"::"r"(clk_mst_spd), "r"(portId));
configure_out_port_no_ready(p_spdif_tx, clk_mst_spd, 0);
set_clock_fall_delay(clk_mst_spd, 7);
start_clock(clk_mst_spd);
while(1)
{
spdif_tx(p_spdif_tx, c_spdif_tx);
}
}
#endif
void usb_audio_io(chanend ?c_aud_in,
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
chanend c_spdif_tx,
#endif
#if (MIXER)
chanend c_mix_ctl,
#endif
streaming chanend ?c_spdif_rx,
streaming chanend ?c_adat_rx,
chanend ?c_clk_ctl,
chanend ?c_clk_int
#if (XUD_TILE != 0) && (AUDIO_IO_TILE == 0) && (XUA_DFU_EN == 1)
, server interface i_dfu ?dfuInterface
#endif
#if (XUA_NUM_PDM_MICS > 0)
, chanend c_pdm_pcm
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, client interface pll_ref_if i_pll_ref
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, chanend c_audio_rate_change
#endif
#if ((XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
, port p_for_mclk_count_aud
, chanend c_sw_pll
#endif
)
{
#if (MIXER)
chan c_mix_out;
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
chan c_dig_rx;
chan c_audio_rate_change; /* Notification of new mclk freq to clockgen and synch */
#if XUA_USE_SW_PLL
/* Connect p_for_mclk_count_aud to clk_audio_mclk so we can count mclks/timestamp in digital rx*/
unsigned x = 0;
asm("ldw %0, dp[clk_audio_mclk]":"=r"(x));
asm("setclk res[%0], %1"::"r"(p_for_mclk_count_aud), "r"(x));
#endif /* XUA_USE_SW_PLL */
#endif /* (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) */
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE == AUDIO_IO_TILE)
chan c_spdif_tx;
/* Setup S/PDIF tx port - note this is done before par since sharing clock-block/port */
spdif_tx_port_config(p_spdif_tx, clk_audio_mclk, p_mclk_in, 7);
#endif
par
{
#if (MIXER && XUA_USB_EN)
/* Mixer cores(s) */
{
thread_speed();
mixer(c_aud_in, c_mix_out, c_mix_ctl);
}
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE == AUDIO_IO_TILE)
while(1)
{
spdif_tx(p_spdif_tx, c_spdif_tx);
}
#endif
/* Audio I/O core (pars additional S/PDIF TX Core) */
{
thread_speed();
#if (MIXER)
#define AUDIO_CHANNEL c_mix_out
#else
#define AUDIO_CHANNEL c_aud_in
#endif
XUA_AudioHub(AUDIO_CHANNEL, clk_audio_mclk, clk_audio_bclk, p_mclk_in, p_lrclk, p_bclk, p_i2s_dac, p_i2s_adc
#if (XUA_SPDIF_TX_EN) //&& (SPDIF_TX_TILE != AUDIO_IO_TILE)
, c_spdif_tx
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, c_dig_rx
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, c_audio_rate_change
#endif
#if (XUD_TILE != 0) && (AUDIO_IO_TILE == 0) && (XUA_DFU_EN == 1)
, dfuInterface
#endif
#if (XUA_NUM_PDM_MICS > 0)
, c_pdm_pcm
#endif
);
}
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
{
/* ClockGen must currently run on same tile as AudioHub due to shared memory buffer
* However, due to the use of an interface the pll reference signal port can be on another tile
*/
thread_speed();
clockGen( c_spdif_rx,
c_adat_rx,
i_pll_ref,
c_dig_rx,
c_clk_ctl,
c_clk_int,
c_audio_rate_change
#if XUA_USE_SW_PLL
, p_for_mclk_count_aud
, c_sw_pll
#endif
);
}
#endif
} // par
}
#ifndef USER_MAIN_DECLARATIONS
#define USER_MAIN_DECLARATIONS
#endif
#ifndef USER_MAIN_CORES
#define USER_MAIN_CORES
#endif
//extern unsafe client interface i2c_master_if i_i2c_client;
//extern unsafe client interface i2c_master_if i_i2c_client_t0;
extern void dsp_core0(void);
extern void board_setup();
extern void dsp_main (streaming chanend c_data);
extern void UserBufferForwardingTask_XC(unsigned c_dsp, unsigned c_init);
extern void SetEx3dHidChan (chanend c);
extern int dsp_worker_tile(chanend c_dsp_to_ex3d, int worker_id);
//extern int dsp_worker_tile_1(chanend c_dsp_to_ex3d, int worker_id);
extern void ex3d_task();
extern void hid_button_task(chanend cc_mic_level, chanend c_hid, chanend c_hidSendData, chanend c_uac_vol, chanend c_ex3d_hid_cmd);
#if HID_DFU_EN
extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx, streaming chanend c_dfu_rx, chanend c_mic_det);
#else
extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol, chanend c_audiohw_rx, chanend c_mic_det);
#endif
extern void dnr_dsp_proc_task(void);
extern unsafe chanend uc_dsp_to_ex3d[DSP_WORKER_COUNT];
extern unsafe chanend uc_dsp_to_dnr_t1;
extern unsafe chanend uc_key_to_ubm_t0;
extern unsafe chanend uc_audiohw;
#if HID_DFU_EN
extern unsafe streaming chanend uc_dfu;
#endif
extern void key_sender(chanend c_key);
extern void key_receiver(chanend c_key);
extern void mute_handler(chanend c_mic_det);
/* Main for USB Audio Applications */
int main()
{
#if !XUA_USB_EN
#define c_mix_out null
#else
chan c_mix_out;
#endif
#ifdef MIDI
chan c_midi;
#endif
#ifdef IAP
chan c_iap;
#ifdef IAP_EA_NATIVE_TRANS
chan c_ea_data;
#endif
#endif
#if (MIXER)
chan c_mix_ctl;
#endif
#if (XUA_SPDIF_RX_EN)
streaming chan c_spdif_rx;
#else
#define c_spdif_rx null
#endif
#if (XUA_ADAT_RX_EN)
streaming chan c_adat_rx;
#else
#define c_adat_rx null
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
chan c_spdif_tx;
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
chan c_clk_ctl;
chan c_clk_int;
#else
#define c_clk_int null
#define c_clk_ctl null
#endif
#if (XUA_DFU_EN == 1)
interface i_dfu dfuInterface;
#else
#define dfuInterface null
#endif
#if (XUA_NUM_PDM_MICS > 0)
chan c_pdm_pcm;
#endif
#if (((XUA_SYNCMODE == XUA_SYNCMODE_SYNC && !XUA_USE_SW_PLL) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) )
interface pll_ref_if i_pll_ref;
#endif
#if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
chan c_sw_pll;
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
chan c_audio_rate_change; /* Notification of new mclk freq to ep_buffer */
#endif
chan c_sof;
chan c_xud_out[ENDPOINT_COUNT_OUT]; /* Endpoint channels for XUD */
chan c_xud_in[ENDPOINT_COUNT_IN];
/* Used to communicate controls/setting from XUA_Endpoint0() to the Audio/Buffering sub-system */
chan c_aud_ctl;
#if (!MIXER)
#define c_mix_ctl null
#endif
#ifdef IAP_EA_NATIVE_TRANS
chan c_EANativeTransport_ctrl;
#else
#define c_EANativeTransport_ctrl null
#endif
//#if (HID_CONTROLS > 0)
// chan c_hid;
//#endif
USER_MAIN_DECLARATIONS
chan c_dsp_to_ex3d[DSP_WORKER_COUNT];
chan cc_mic_level;
chan c_audiohw;
#if HID_DFU_EN
streaming chan c_dfu;
#endif
chan c_key; chan c_hidSendData;
chan c_hidRcvData;
streaming chan c_eq_data;
streaming chan c_ubm_init;
chan c_uac_vol;
chan c_ex3d_hid_cmd;
chan c_mic_det;
par
{
USER_MAIN_CORES
on tile[1] : {
par {
// Forwarder Task on its own core
{
unsigned u_dsp, u_init;
asm("mov %0, %1" : "=r"(u_dsp) : "r"(c_eq_data));
asm("mov %0, %1" : "=r"(u_init) : "r"(c_ubm_init));
UserBufferForwardingTask_C(u_dsp, u_init);
}
// HID & Control sequence on its own core
unsafe {
uc_audiohw = (chanend)c_audiohw;
hid_button_task(cc_mic_level, c_hidRcvData, c_hidSendData, c_uac_vol, c_ex3d_hid_cmd);
}
#if USE_EX3D == 1
// Workers on their own cores
par(int i = 0; i < DSP_WORKER_COUNT; i++)
dsp_worker_tile(c_dsp_to_ex3d[i], i);
// EX3D Task sequence on its own core
unsafe {
delay_milliseconds(200);
key_sender(c_key);
for (int i = 0; i < DSP_WORKER_COUNT; i++)
uc_dsp_to_ex3d[i] = (chanend)c_dsp_to_ex3d[i];
ex3d_task();
}
#endif
}
}
on tile[1]: mute_handler(c_mic_det);
on tile[0] : {
par {
{
#if USE_EX3D == 1
unsafe { key_receiver(c_key); }
#endif
AudioHwRemote(c_hidSendData, cc_mic_level, c_uac_vol, c_audiohw
#if HID_DFU_EN
, c_dfu
#endif
, c_mic_det
);
}
}
}
#if EQ_EN == 1
on tile[0] : {
{
#if HID_DFU_EN
unsafe {
uc_dfu = (streaming chanend)c_dfu;
}
#endif
dsp_core0();
}
}
on tile[0] : { dsp_main(c_eq_data); }
#endif
#if DNR_ENABLE == 1
on tile[0] : { dnr_dsp_proc_task(); }
#endif
#if (((XUA_SYNCMODE == XUA_SYNCMODE_SYNC && !XUA_USE_SW_PLL) || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN))
on tile[PLL_REF_TILE]: PllRefPinTask(i_pll_ref, p_pll_ref);
#endif
on tile[XUD_TILE]:
par
{
#if XUA_USB_EN
#if ((XUD_TILE == 0) && (XUA_DFU_EN == 1))
/* Check if USB is on the flash tile (tile 0) */
/* Expect to be distrbuted into XUA_Endpoint0() */
[[distribute]]
DFUHandler(dfuInterface, null);
#endif
/* Core USB task, buffering, USB etc */
{
#ifdef XUD_PRIORITY_HIGH
set_core_high_priority_on();
#endif
/* Run UAC2.0 at high-speed, UAC1.0 at full-speed */
unsigned usbSpeed = (AUDIO_CLASS == 2) ? XUD_SPEED_HS : XUD_SPEED_FS;
unsigned xudPwrCfg = (XUA_POWERMODE == XUA_POWERMODE_SELF) ? XUD_PWR_SELF : XUD_PWR_BUS;
/* USB interface core */
XUD_Main(c_xud_out, ENDPOINT_COUNT_OUT, c_xud_in, ENDPOINT_COUNT_IN,
c_sof, epTypeTableOut, epTypeTableIn, usbSpeed, xudPwrCfg);
}
#if (NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0) || XUA_HID_ENABLED || defined(MIDI)
/* Core USB audio task, buffering, USB etc */
{
unsigned x;
thread_speed();
/* Attach mclk count port to mclk clock-block (for feedback) */
//set_port_clock(p_for_mclk_count, clk_audio_mclk);
#if(AUDIO_IO_TILE != XUD_TILE)
set_clock_src(clk_audio_mclk_usb, p_mclk_in_usb);
set_port_clock(p_for_mclk_count, clk_audio_mclk_usb);
start_clock(clk_audio_mclk_usb);
#else
/* Clock port from same clock-block as I2S */
/* TODO remove asm() */
asm("ldw %0, dp[clk_audio_mclk]":"=r"(x));
asm("setclk res[%0], %1"::"r"(p_for_mclk_count), "r"(x));
#endif
/* Endpoint & audio buffering cores - buffers all EP's other than 0 */
XUA_Buffer(
#if (NUM_USB_CHAN_OUT > 0)
c_xud_out[ENDPOINT_NUMBER_OUT_AUDIO], /* Audio Out*/
#endif
#if (NUM_USB_CHAN_IN > 0)
c_xud_in[ENDPOINT_NUMBER_IN_AUDIO], /* Audio In */
#endif
#if (NUM_USB_CHAN_OUT > 0) && ((NUM_USB_CHAN_IN == 0) || defined(UAC_FORCE_FEEDBACK_EP))
c_xud_in[ENDPOINT_NUMBER_IN_FEEDBACK], /* Audio FB */
#endif
#ifdef MIDI
c_xud_out[ENDPOINT_NUMBER_OUT_MIDI], /* MIDI Out */ // 2
c_xud_in[ENDPOINT_NUMBER_IN_MIDI], /* MIDI In */ // 4
c_midi,
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
/* Audio Interrupt - only used for interrupts on external clock change */
c_xud_in[ENDPOINT_NUMBER_IN_INTERRUPT],
c_clk_int,
#endif
c_sof, c_aud_ctl, p_for_mclk_count
#if (XUA_HID_ENABLED)
, c_xud_in[ENDPOINT_NUMBER_IN_HID]
#endif
, c_mix_out
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, c_audio_rate_change
#if (!XUA_USE_SW_PLL)
, i_pll_ref
#else
, c_sw_pll
#endif
#endif
);
//:
}
#endif
/* Endpoint 0 Core */
{
thread_speed();
#if (USE_EX3D == 1) && (HID_CONTROLS > 0)
SetEx3dHidChan(c_ex3d_hid_cmd);
XUA_Endpoint0( c_xud_out[0], c_xud_in[0], c_hidRcvData, c_aud_ctl, c_mix_ctl, c_clk_ctl, c_EANativeTransport_ctrl, dfuInterface VENDOR_REQUESTS_PARAMS_);
#else
XUA_Endpoint0( c_xud_out[0], c_xud_in[0], c_aud_ctl, c_mix_ctl, c_clk_ctl, c_EANativeTransport_ctrl, dfuInterface VENDOR_REQUESTS_PARAMS_);
#endif
}
#endif /* XUA_USB_EN */
}
#if ((XUA_SYNCMODE == XUA_SYNCMODE_SYNC || XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
on tile[AUDIO_IO_TILE]: sw_pll_task(c_sw_pll);
#endif
on tile[AUDIO_IO_TILE]:
{
set_core_high_priority_on();
/* Audio I/O task, includes mixing etc */
usb_audio_io(
#if (NUM_USB_CHAN_OUT > 0) || (NUM_USB_CHAN_IN > 0)
/* Connect audio system to XUA_Buffer(); */
c_mix_out
#else
/* Connect to XUA_Endpoint0() */
c_aud_ctl
#endif
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
, c_spdif_tx
#endif
#if (MIXER)
, c_mix_ctl
#endif
, c_spdif_rx, c_adat_rx, c_clk_ctl, c_clk_int
#if (XUD_TILE != 0) && (AUDIO_IO_TILE == 0) && (XUA_DFU_EN == 1)
, dfuInterface
#endif
#if (XUA_NUM_PDM_MICS > 0)
, c_pdm_pcm
#endif
#if (XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN)
, i_pll_ref
#endif
#if (XUA_SYNCMODE == XUA_SYNCMODE_SYNC)
, c_audio_rate_change
#endif
#if ((XUA_SPDIF_RX_EN || XUA_ADAT_RX_EN) && XUA_USE_SW_PLL)
, p_for_mclk_count_audio
, c_sw_pll
#endif
);
}
#if (XUA_SPDIF_TX_EN) && (SPDIF_TX_TILE != AUDIO_IO_TILE)
on tile[SPDIF_TX_TILE]:
{
thread_speed();
SpdifTxWrapper(c_spdif_tx);
}
#endif
#if defined(MIDI) && defined(IAP) && (IAP_TILE == MIDI_TILE)
/* MIDI and IAP share a core */
on tile[IAP_TILE]:
{
thread_speed();
usb_midi(p_midi_rx, p_midi_tx, clk_midi, c_midi, 0, c_iap, null, null, null);
}
#else
#if defined(MIDI)
/* MIDI core */
on tile[MIDI_TILE]:
{
thread_speed();
usb_midi(p_midi_rx, p_midi_tx, clk_midi, c_midi, 0);
}
#endif
#if defined(IAP)
on tile[IAP_TILE]:
{
thread_speed();
iAP(c_iap, null, null, null);
}
#endif
#endif
#if (XUA_SPDIF_RX_EN)
on tile[XUD_TILE]:
{
thread_speed();
spdif_rx(c_spdif_rx, p_spdif_rx, clk_spd_rx, 192000);
}
#endif
#if (XUA_ADAT_RX_EN)
on stdcore[XUD_TILE] :
{
set_thread_fast_mode_on();
while (1)
{
adatReceiver48000(p_adat_rx, c_adat_rx);
adatReceiver44100(p_adat_rx, c_adat_rx);
}
}
#endif
#if XUA_USB_EN
#if (XUD_TILE != 0) && (AUDIO_IO_TILE != 0) && (XUA_DFU_EN == 1)
/* Run flash code on its own - hope it gets combined */
//#warning Running DFU flash code on its own
on stdcore[0]: DFUHandler(dfuInterface, null);
#endif
#endif
#if (XUA_NUM_PDM_MICS > 0)
/* PDM Mics running on a separate to AudioHub */
on stdcore[PDM_TILE]:
{
mic_array_task(c_mic_pcm);
}
#endif /*XUA_NUM_PDM_MICS > 0*/
}
return 0;
}
#endif

View File

@@ -0,0 +1,128 @@
// Copyright 2021-2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#define DEBUG_PRINT_ENABLE 1
#include <platform.h>
#include <print.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "xc_ptr.h"
#include "share_buffer.h"
#include "debug_print.h"
unsafe streaming chanend uc_eq_data;
unsigned g_current_sample_freq = 0;
extern void UserBufferManagement_ex3d(unsigned sampsFromUsbToAudio[]);
extern void UserBufferManagementInit_ex3d(unsigned sampFreq);
extern uint32_t init_eq_data(unsigned sample_freq);
extern unsigned g_monitor_switch_t1;
unsigned dnr_exchange_buffer(unsigned data);
void SetEqDataChan (streaming chanend c) {
unsafe {
uc_eq_data = c;
}
}
void dsp_main (streaming chanend c_data) {
int play_input[NUM_USB_CHAN_OUT];
int play_output[I2S_CHANS_DAC];
unsigned mic_input[I2S_CHANS_ADC];
int mic_output[I2S_CHANS_ADC];
unsigned sample_freq_old = 0;
play_output[0] = 0;
play_output[1] = 0;
while (1) {
// 用 stestct 区分控制令牌(采样率变更)和数据令牌(音频样本)
if (stestct(c_data)) {
// 控制令牌:采样率变更,执行初始化
sinct(c_data);
unsigned sample_freq;
c_data :> sample_freq;
if ( sample_freq != sample_freq_old)
{
init_eq_data(sample_freq);
clear_ring_buffer(0);
clear_ring_buffer(1);
clear_ring_buffer(2);
clear_ring_buffer(3);
play_output[0] = 0;
play_output[1] = 0;
sample_freq_old = sample_freq;
}
// 回送控制令牌作为确认
soutct(c_data, 0x06);
} else {
// 数据令牌:正常音频处理路径
c_data :> play_input[0];
c_data :> play_input[1];
c_data <: play_output[0];
c_data <: play_output[1];
#if DNR_ENABLE == 1
c_data :> mic_input[1];
c_data <: mic_output[1];
#endif
write_to_ring_buffer(0, play_input[0]);
write_to_ring_buffer(1, play_input[1]);
play_output[0] = read_from_ring_buffer(2);
play_output[1] = read_from_ring_buffer(3);
#if DNR_ENABLE == 1
unsafe {
mic_output[1] = dnr_exchange_buffer(mic_input[1]);
}
#endif
}
}
}
#pragma unsafe arrays
void UserBufferManagementInit(unsigned sampFreq)
{
SET_SHARED_GLOBAL(g_current_sample_freq, sampFreq);
UserBufferManagementInit_ex3d(sampFreq);
unsafe {
// 发送控制令牌 + 采样率给 dsp_main触发初始化
soutct((streaming chanend)uc_eq_data, 0x06);
uc_eq_data <: sampFreq;
// 等待 dsp_main 确认:排空残留数据令牌,等控制令牌回来
int trashbin;
for (;;) {
if (stestct((streaming chanend)uc_eq_data)) {
sinct((streaming chanend)uc_eq_data);
break;
} else {
uc_eq_data :> trashbin;
}
}
}
}
// out port freq_port = PORT_X1D26_27_32_33;
#pragma unsafe arrays
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[])
{
unsigned is_monitor;
UserBufferManagement_ex3d(sampsFromUsbToAudio);
unsafe {
// 数据路径:只传输音频样本,不传采样率(采样率变更由 UserBufferManagementInit 通过控制令牌处理)
uc_eq_data <: sampsFromUsbToAudio[0];
uc_eq_data <: sampsFromUsbToAudio[1];
uc_eq_data :> sampsFromUsbToAudio[0];
uc_eq_data :> sampsFromUsbToAudio[1];
#if DNR_ENABLE == 1
uc_eq_data <: sampsFromAudioToUsb[1];
uc_eq_data :> sampsFromAudioToUsb[1];
sampsFromAudioToUsb[0] = sampsFromAudioToUsb[1];
#endif
}
GET_SHARED_GLOBAL(is_monitor, g_monitor_switch_t1);
if (is_monitor) {
sampsFromUsbToAudio[0] += (sampsFromAudioToUsb[0]);
sampsFromUsbToAudio[1] += (sampsFromAudioToUsb[1]);
}
}

View File

@@ -0,0 +1,207 @@
// Copyright 2021-2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#define DEBUG_PRINT_ENABLE 1
#include <platform.h>
#include <print.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "xc_ptr.h"
#include "share_buffer.h"
#include "debug_print.h"
#include "ubm_memory.h"
unsafe streaming chanend uc_eq_data;
unsafe streaming chanend uc_ubm_init;
unsigned g_current_sample_freq = 0;
extern void UserBufferManagement_ex3d(unsigned sampsFromUsbToAudio[]);
extern void UserBufferManagementInit_ex3d(unsigned sampFreq);
extern uint32_t init_eq_data(unsigned sample_freq);
extern unsigned g_monitor_switch_t1;
unsigned dnr_exchange_buffer(unsigned data);
void SetEqDataChan (streaming chanend c) {
unsafe {
uc_eq_data = c;
}
}
void SetUbmInitChan (streaming chanend c) {
unsafe {
uc_ubm_init = c;
}
}
void UserBufferForwardingTask(streaming chanend c_dsp, streaming chanend c_init) {
unsigned sample_freq = 0;
unsafe {
ubm_shared_t * unsafe p = (ubm_shared_t * unsafe)get_ubm_shared_ptr();
while(1) {
select {
// 1. Handle Init Request via Channel
case c_init :> sample_freq:
soutct(c_dsp, 0x06);
c_dsp <: sample_freq;
// wait for ack from dsp_main (Tile 0)
int trashbin;
for (;;) {
if (stestct(c_dsp)) {
sinct(c_dsp);
break;
} else {
c_dsp :> trashbin;
}
}
c_init <: 1; // Send ack back
break;
// 2. Forward samples to dsp_main on Tile 0
default:
if (p->head != p->tail) {
unsigned t = p->tail;
unsigned p_in[2];
#if DNR_ENABLE == 1
unsigned dnr_in;
#endif
unsigned p_out[2];
#if DNR_ENABLE == 1
unsigned dnr_out;
#endif
p_in[0] = p->usb_to_dsp[0][t];
p_in[1] = p->usb_to_dsp[1][t];
#if DNR_ENABLE == 1
dnr_in = p->dnr_to_dsp[t];
#endif
p->tail = (t + 1) & 3;
// Talk to dsp_main (Tile 0)
c_dsp <: p_in[0];
c_dsp <: p_in[1];
c_dsp :> p_out[0];
c_dsp :> p_out[1];
#if DNR_ENABLE == 1
c_dsp <: dnr_in;
c_dsp :> dnr_out;
#endif
// Put processed sample back
unsigned fh = p->f_head;
p->usb_from_dsp[0][fh] = p_out[0];
p->usb_from_dsp[1][fh] = p_out[1];
#if DNR_ENABLE == 1
p->dnr_from_dsp[fh] = dnr_out;
#endif
p->f_head = (fh + 1) & 3;
}
break;
}
}
}
}
void dsp_main (streaming chanend c_data) {
int play_input[NUM_USB_CHAN_OUT];
int play_output[I2S_CHANS_DAC];
unsigned sample_freq_old = 0;
#if DNR_ENABLE == 1
static int mic_output_dnr = 0; // 必须为 static 以保持采样间状态并回传上一结果
#endif
play_output[0] = 0;
play_output[1] = 0;
while (1) {
if (stestct(c_data)) {
sinct(c_data);
unsigned sample_freq;
c_data :> sample_freq;
if ( sample_freq != sample_freq_old)
{
init_eq_data(sample_freq);
clear_ring_buffer(0);
clear_ring_buffer(1);
clear_ring_buffer(2);
clear_ring_buffer(3);
play_output[0] = 0;
play_output[1] = 0;
sample_freq_old = sample_freq;
}
soutct(c_data, 0x06);
} else {
c_data :> play_input[0];
c_data :> play_input[1];
c_data <: play_output[0];
c_data <: play_output[1];
#if DNR_ENABLE == 1
unsigned mic_input_dnr;
c_data :> mic_input_dnr;
c_data <: mic_output_dnr; // 发送上一次的处理结果,避免阻塞
// 在 Tile 0 上执行 DNR 处理(与 dnr_dsp_proc_task 共享内存)
// 注意:即便 DNR level 为 0也必须调用 dnr_exchange_buffer 以维持缓冲区轮转和数据直通
unsafe {
mic_output_dnr = (int)dnr_exchange_buffer(mic_input_dnr);
}
#endif
write_to_ring_buffer(0, play_input[0]);
write_to_ring_buffer(1, play_input[1]);
play_output[0] = read_from_ring_buffer(2);
play_output[1] = read_from_ring_buffer(3);
}
}
}
#pragma unsafe arrays
void UserBufferManagementInit(unsigned sampFreq)
{
SET_SHARED_GLOBAL(g_current_sample_freq, sampFreq);
UserBufferManagementInit_ex3d(sampFreq);
unsafe {
uc_ubm_init <: sampFreq;
int ack;
uc_ubm_init :> ack;
}
}
// out port freq_port = PORT_X1D26_27_32_33;
#pragma unsafe arrays
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[])
{
unsigned is_monitor;
UserBufferManagement_ex3d(sampsFromUsbToAudio);
unsafe {
ubm_shared_t * unsafe p = (ubm_shared_t * unsafe)get_ubm_shared_ptr();
// 1. Push new samples into ring buffer
unsigned h = p->head;
p->usb_to_dsp[0][h] = sampsFromUsbToAudio[0];
p->usb_to_dsp[1][h] = sampsFromUsbToAudio[1];
#if DNR_ENABLE == 1
p->dnr_to_dsp[h] = sampsFromAudioToUsb[1];
#endif
p->head = (h + 1) & 3;
// 2. Pull processed samples from ring buffer
if (p->f_head != p->f_tail) {
unsigned ft = p->f_tail;
sampsFromUsbToAudio[0] = p->usb_from_dsp[0][ft];
sampsFromUsbToAudio[1] = p->usb_from_dsp[1][ft];
#if DNR_ENABLE == 1
sampsFromAudioToUsb[1] = p->dnr_from_dsp[ft];
sampsFromAudioToUsb[0] = sampsFromAudioToUsb[1]; // 拷贝处理后的单声道到双声道
#endif
p->f_tail = (ft + 1) & 3;
}
}
GET_SHARED_GLOBAL(is_monitor, g_monitor_switch_t1);
if (is_monitor) {
sampsFromUsbToAudio[0] += (sampsFromAudioToUsb[0]);
sampsFromUsbToAudio[1] += (sampsFromAudioToUsb[1]);
}
}

View File

@@ -0,0 +1,200 @@
// Copyright 2021-2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#define DEBUG_PRINT_ENABLE 1
#include <platform.h>
#include <print.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "xc_ptr.h"
#include "share_buffer.h"
#include "debug_print.h"
#include "ubm_memory.h"
unsigned g_current_sample_freq = 0;
extern void UserBufferManagement_ex3d(unsigned sampsFromUsbToAudio[]);
extern void UserBufferManagementInit_ex3d(unsigned sampFreq);
extern uint32_t init_eq_data(unsigned sample_freq);
extern unsigned g_monitor_switch_t1;
unsigned dnr_exchange_buffer(unsigned data);
// 保持定义以兼容 main.xc
void SetEqDataChan (chanend c) {}
void SetUbmInitChan (chanend c) {}
// XC 中实现转发任务。使用 unsigned 参数避开 XC 编译器的并行资源分析 Bug。
void UserBufferForwardingTask_XC(unsigned c_dsp_val, unsigned c_init_val) {
unsigned sample_freq = 0;
// 设置 Init 通道供回调使用
set_ubm_init_chan_c(c_init_val);
unsafe {
ubm_shared_t * unsafe p = (ubm_shared_t * unsafe)get_ubm_shared_ptr();
while(1) {
// 1. 处理初始化请求
int is_ct;
asm("testct %0, res[%1]" : "=r"(is_ct) : "r"(c_init_val));
if (is_ct) {
asm("in %0, res[%1]" : "=r"(sample_freq) : "r"(c_init_val));
asm("outct res[%0], %1" :: "r"(c_dsp_val), "r"(0x06));
asm("out res[%0], %1" :: "r"(c_dsp_val), "r"(sample_freq));
// 等待确认
while (1) {
int dsp_ct;
asm("testct %0, res[%1]" : "=r"(dsp_ct) : "r"(c_dsp_val));
if (dsp_ct) {
unsigned tmp;
asm("inct %0, res[%1]" : "=r"(tmp) : "r"(c_dsp_val));
break;
} else {
unsigned trash;
asm("in %0, res[%1]" : "=r"(trash) : "r"(c_dsp_val));
}
}
asm("out res[%0], %1" :: "r"(c_init_val), "r"(1));
}
// 2. 处理音频转发
if (p->head != p->tail) {
unsigned t = p->tail;
unsigned p_in[NUM_USB_CHAN_OUT];
unsigned p_out[2];
#if DNR_ENABLE == 1
unsigned dnr_in = p->dnr_to_dsp[t];
unsigned dnr_out;
#endif
for(int i=0; i<NUM_USB_CHAN_OUT; i++) {
p_in[i] = p->usb_to_dsp[i][t];
}
p->tail = (t + 1) & 3;
// 在此处调用算法,确保 XC 宏定义完全有效
UserBufferManagement_ex3d(p_in);
// 发送给 Tile 0 (EQ 处理)
asm("out res[%0], %1" :: "r"(c_dsp_val), "r"(p_in[0]));
asm("out res[%0], %1" :: "r"(c_dsp_val), "r"(p_in[1]));
asm("in %0, res[%1]" : "=r"(p_out[0]) : "r"(c_dsp_val));
asm("in %0, res[%1]" : "=r"(p_out[1]) : "r"(c_dsp_val));
#if DNR_ENABLE == 1
// 发送给 Tile 0 (DNR 处理)
asm("out res[%0], %1" :: "r"(c_dsp_val), "r"(dnr_in));
asm("in %0, res[%1]" : "=r"(dnr_out) : "r"(c_dsp_val));
#endif
// 写回结果
unsigned fh = p->f_head;
p->usb_from_dsp[0][fh] = p_out[0];
p->usb_from_dsp[1][fh] = p_out[1];
#if DNR_ENABLE == 1
p->dnr_from_dsp[fh] = dnr_out;
#endif
p->f_head = (fh + 1) & 3;
}
}
}
}
void dsp_main (streaming chanend c_data) {
int play_input[2];
int play_output[2];
unsigned sample_freq_old = 0;
#if DNR_ENABLE == 1
static int mic_output_dnr = 0;
#endif
play_output[0] = 0;
play_output[1] = 0;
while (1) {
if (stestct(c_data)) {
sinct(c_data);
unsigned sample_freq;
c_data :> sample_freq;
if ( sample_freq != sample_freq_old)
{
init_eq_data(sample_freq);
clear_ring_buffer(0);
clear_ring_buffer(1);
clear_ring_buffer(2);
clear_ring_buffer(3);
play_output[0] = 0;
play_output[1] = 0;
sample_freq_old = sample_freq;
}
soutct(c_data, 0x06);
} else {
c_data :> play_input[0];
c_data :> play_input[1];
c_data <: play_output[0];
c_data <: play_output[1];
#if DNR_ENABLE == 1
unsigned mic_input_dnr;
c_data :> mic_input_dnr;
c_data <: mic_output_dnr;
unsafe {
mic_output_dnr = (int)dnr_exchange_buffer(mic_input_dnr);
}
#endif
write_to_ring_buffer(0, play_input[0]);
write_to_ring_buffer(1, play_input[1]);
play_output[0] = read_from_ring_buffer(2);
play_output[1] = read_from_ring_buffer(3);
}
}
}
#pragma unsafe arrays
void UserBufferManagementInit(unsigned sampFreq)
{
SET_SHARED_GLOBAL(g_current_sample_freq, sampFreq);
UserBufferManagementInit_ex3d(sampFreq);
unsigned val = get_ubm_init_chan_c();
if (val != 0) {
unsafe {
asm("out res[%0], %1" :: "r"(val), "r"(sampFreq));
unsigned ack;
asm("in %0, res[%1]" : "=r"(ack) : "r"(val));
}
}
}
#pragma unsafe arrays
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[])
{
unsigned is_monitor;
unsafe {
ubm_shared_t * unsafe p = (ubm_shared_t * unsafe)get_ubm_shared_ptr();
unsigned h = p->head;
for(int i=0; i<NUM_USB_CHAN_OUT; i++) {
p->usb_to_dsp[i][h] = sampsFromUsbToAudio[i];
}
#if DNR_ENABLE == 1
p->dnr_to_dsp[h] = sampsFromAudioToUsb[1];
#endif
p->head = (h + 1) & 3;
if (p->f_head != p->f_tail) {
unsigned ft = p->f_tail;
sampsFromUsbToAudio[0] = p->usb_from_dsp[0][ft];
sampsFromUsbToAudio[1] = p->usb_from_dsp[1][ft];
#if DNR_ENABLE == 1
sampsFromAudioToUsb[1] = p->dnr_from_dsp[ft];
sampsFromAudioToUsb[0] = sampsFromAudioToUsb[1];
#endif
p->f_tail = (ft + 1) & 3;
}
}
GET_SHARED_GLOBAL(is_monitor, g_monitor_switch_t1);
if (is_monitor) {
sampsFromUsbToAudio[0] += (sampsFromAudioToUsb[0]);
sampsFromUsbToAudio[1] += (sampsFromAudioToUsb[1]);
}
}

View File

@@ -0,0 +1,208 @@
// Copyright 2021-2024 XMOS LIMITED.
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
#define DEBUG_PRINT_ENABLE 1
#include <platform.h>
#include <print.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include "xc_ptr.h"
#include "share_buffer.h"
#include "debug_print.h"
#include "ubm_memory.h"
unsafe streaming chanend uc_eq_data;
unsafe streaming chanend uc_ubm_init;
unsigned g_current_sample_freq = 0;
extern void UserBufferManagement_ex3d(unsigned sampsFromUsbToAudio[]);
extern void UserBufferManagementInit_ex3d(unsigned sampFreq);
extern uint32_t init_eq_data(unsigned sample_freq);
extern unsigned g_monitor_switch_t1;
unsigned dnr_exchange_buffer(unsigned data);
void SetEqDataChan (streaming chanend c) {
unsafe {
uc_eq_data = c;
}
}
void SetUbmInitChan (streaming chanend c) {
unsafe {
uc_ubm_init = c;
}
}
void UserBufferForwardingTask(streaming chanend c_dsp, streaming chanend c_init) {
unsigned sample_freq = 0;
unsafe {
ubm_shared_t * unsafe p = (ubm_shared_t * unsafe)get_ubm_shared_ptr();
while(1) {
select {
// 1. Handle Init Request via Channel
case c_init :> sample_freq:
soutct(c_dsp, 0x06);
c_dsp <: sample_freq;
// wait for ack from dsp_main (Tile 0)
int trashbin;
for (;;) {
if (stestct(c_dsp)) {
sinct(c_dsp);
break;
} else {
c_dsp :> trashbin;
}
}
c_init <: 1; // Send ack back
break;
// 2. Forward samples to dsp_main on Tile 0
default:
if (p->head != p->tail) {
unsigned t = p->tail;
unsigned p_in[NUM_USB_CHAN_OUT];
#if DNR_ENABLE == 1
unsigned dnr_in;
#endif
unsigned p_out[2];
#if DNR_ENABLE == 1
unsigned dnr_out;
#endif
for(int i=0; i<NUM_USB_CHAN_OUT; i++) {
p_in[i] = p->usb_to_dsp[i][t];
}
#if DNR_ENABLE == 1
dnr_in = p->dnr_to_dsp[t];
#endif
p->tail = (t + 1) & 3;
// 在此处调用算法,确保 XC 宏定义完全有效
UserBufferManagement_ex3d(p_in);
// Talk to dsp_main (Tile 0)
c_dsp <: p_in[0];
c_dsp <: p_in[1];
c_dsp :> p_out[0];
c_dsp :> p_out[1];
#if DNR_ENABLE == 1
c_dsp <: dnr_in;
c_dsp :> dnr_out;
#endif
// Put processed sample back
unsigned fh = p->f_head;
p->usb_from_dsp[0][fh] = p_out[0];
p->usb_from_dsp[1][fh] = p_out[1];
#if DNR_ENABLE == 1
p->dnr_from_dsp[fh] = dnr_out;
#endif
p->f_head = (fh + 1) & 3;
}
break;
}
}
}
}
void dsp_main (streaming chanend c_data) {
int play_input[NUM_USB_CHAN_OUT];
int play_output[I2S_CHANS_DAC];
unsigned sample_freq_old = 0;
#if DNR_ENABLE == 1
static int mic_output_dnr = 0; // 必须为 static 以保持采样间状态并回传上一结果
#endif
play_output[0] = 0;
play_output[1] = 0;
while (1) {
if (stestct(c_data)) {
sinct(c_data);
unsigned sample_freq;
c_data :> sample_freq;
if ( sample_freq != sample_freq_old)
{
init_eq_data(sample_freq);
clear_ring_buffer(0);
clear_ring_buffer(1);
clear_ring_buffer(2);
clear_ring_buffer(3);
play_output[0] = 0;
play_output[1] = 0;
sample_freq_old = sample_freq;
}
soutct(c_data, 0x06);
} else {
c_data :> play_input[0];
c_data :> play_input[1];
c_data <: play_output[0];
c_data <: play_output[1];
#if DNR_ENABLE == 1
unsigned mic_input_dnr;
c_data :> mic_input_dnr;
c_data <: mic_output_dnr; // 发送上一次的处理结果,避免阻塞
// 在 Tile 0 上执行 DNR 处理(与 dnr_dsp_proc_task 共享内存)
// 注意:即便 DNR level 为 0也必须调用 dnr_exchange_buffer 以维持缓冲区轮转和数据直通
unsafe {
mic_output_dnr = (int)dnr_exchange_buffer(mic_input_dnr);
}
#endif
write_to_ring_buffer(0, play_input[0]);
write_to_ring_buffer(1, play_input[1]);
play_output[0] = read_from_ring_buffer(2);
play_output[1] = read_from_ring_buffer(3);
}
}
}
#pragma unsafe arrays
void UserBufferManagementInit(unsigned sampFreq)
{
SET_SHARED_GLOBAL(g_current_sample_freq, sampFreq);
UserBufferManagementInit_ex3d(sampFreq);
unsafe {
uc_ubm_init <: sampFreq;
int ack;
uc_ubm_init :> ack;
}
}
// out port freq_port = PORT_X1D26_27_32_33;
#pragma unsafe arrays
void UserBufferManagement(unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[])
{
unsigned is_monitor;
unsafe {
ubm_shared_t * unsafe p = (ubm_shared_t * unsafe)get_ubm_shared_ptr();
// 1. Push new samples into ring buffer
unsigned h = p->head;
for(int i=0; i<NUM_USB_CHAN_OUT; i++) {
p->usb_to_dsp[i][h] = sampsFromUsbToAudio[i];
}
#if DNR_ENABLE == 1
p->dnr_to_dsp[h] = sampsFromAudioToUsb[1];
#endif
p->head = (h + 1) & 3;
// 2. Pull processed samples from ring buffer
if (p->f_head != p->f_tail) {
unsigned ft = p->f_tail;
sampsFromUsbToAudio[0] = p->usb_from_dsp[0][ft];
sampsFromUsbToAudio[1] = p->usb_from_dsp[1][ft];
#if DNR_ENABLE == 1
sampsFromAudioToUsb[1] = p->dnr_from_dsp[ft];
sampsFromAudioToUsb[0] = sampsFromAudioToUsb[1]; // 拷贝处理后的单声道到双声道
#endif
p->f_tail = (ft + 1) & 3;
}
}
GET_SHARED_GLOBAL(is_monitor, g_monitor_switch_t1);
if (is_monitor) {
sampsFromUsbToAudio[0] += (sampsFromAudioToUsb[0]);
sampsFromUsbToAudio[1] += (sampsFromAudioToUsb[1]);
}
}

View File

@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<xSCOPEconfig enabled="false" initTracing="true" ioMode="none">
</xSCOPEconfig>

View File

@@ -1,283 +0,0 @@
cmake_minimum_required(VERSION 3.21)
include($ENV{XMOS_CMAKE_PATH}/xcommon.cmake)
project(app_usb_aud_sy102)
set(APP_HW_TARGET synido.xn)
include(${CMAKE_CURRENT_LIST_DIR}/../deps.cmake)
set(APP_PCA_ENABLE ON)
###=========================================================================###
set(TARGET_HW_PHATEN_GSV2 ON)
set(CODEC_IS_AIC3204 ON)
# Configure host os detection here... (Windows or Non-Windows)
#-----------------------------------------------------------------------------#
# Host OS detection, set HOST_OS_DETECTION to ON
set(HOST_OS_DETECTION ON)
###=========================================================================###
# Customer
if (TARGET_HW_PHATEN_GSV2)
message("-- Building for PHATEN_GSv2 ---")
set(TARGET_BOARD PHATEN_GSV2)
set(APP_HW_TARGET synido.xn)
endif()
# CODEC IC
if (CODEC_IS_AIC3204)
message("-- DAC: AIC3204 ---")
set(CODEC_IC CODEC_AIC3204)
endif()
# Host OS detection
if (HOST_OS_DETECTION)
message("-- Host OS detection (Windows/Non-Windows) enabled ---")
set(EXTRA_BUILD_FLAGS ${EXTRA_BUILD_FLAGS} -DHOST_OS_DETECTION)
endif()
# Firmware version (maps to BCD_DEVICE_J.M.N in USB descriptor)
set(FW_VER_J 1)
set(FW_VER_M 1)
set(FW_VER_N 15)
set(FW_VERSION "v${FW_VER_J}.${FW_VER_M}.${FW_VER_N}")
set(SW_USB_AUDIO_FLAGS ${EXTRA_BUILD_FLAGS} -Os
-report
-L${CMAKE_CURRENT_LIST_DIR}/../../lib_ex3d/lib_ex3d/lib
-lquadflash
-g
#-fxscope
-DUSB_TILE=tile[0]
-DXUA_QUAD_SPI_FLASH=1
-D${TARGET_BOARD}
-DBCD_DEVICE_J=${FW_VER_J}
-DBCD_DEVICE_M=${FW_VER_M}
-DBCD_DEVICE_N=${FW_VER_N}
-D${CODEC_IC}
-DWINDOWS_OS_DESCRIPTOR_SUPPORT)
set(SW_USB_FACT_FLAGS ${EXTRA_BUILD_FLAGS} -Os
-report
-L${CMAKE_CURRENT_LIST_DIR}/../../lib_ex3d/lib_ex3d/lib
-lquadflash
-g
#-fxscope
-DUSB_TILE=tile[0]
-DXUA_QUAD_SPI_FLASH=1
-D${TARGET_BOARD}
-DBCD_DEVICE_J=5
-DBCD_DEVICE_M=5
-DBCD_DEVICE_N=7
-D${CODEC_IC}
-DWINDOWS_OS_DESCRIPTOR_SUPPORT)
LINK_DIRECTORIES(${CMAKE_CURRENT_LIST_DIR}/../../lib_dnr/lib_dnr)
set(APP_COMPILER_FLAGS_f5_music_uac1 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
-DI2S_CHANS_ADC=2
-DAUDIO_CLASS=1
-DMIN_FREQ=48000
-DMAX_FREQ=48000
-DMCLK_441=512*44100
-DMCLK_48=512*48000
-DUAC1_MODE=1
-DF5_MUSIC_UAC1=1
#-DUSE_EX3D
-DMIXER=0
#-ldnr_11ms
#-DDNR_ENABLE=1
#-llib_ex3d_all
-DEQ_EN=1
-DEX3D_SF_NUM=3
-DNUM_USB_CHAN_OUT=8
-DNUM_USB_CHAN_OUT_FS=2
-DNUM_USB_CHAN_IN=2
-DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=16
-DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=16
-DINPUT_FORMAT_COUNT=1
-DOUTPUT_FORMAT_COUNT=1
#-DNUM_EX3D_CHAN_OUT=2
-DMIN_VOLUME=0xE000
-DINPUT_VOLUME_CONTROL=0
-DOUTPUT_VOLUME_CONTROL=0
#-DDEBUG_MEMORY_LOG_ENABLED=1
-DXUA_DFU_EN=0
-DHID_DFU_EN=1
-DHID_CONTROLS_UAC1=1
#-DIR_SWITCHING_MODE
-DHID_CONTROLS=1)
set(APP_COMPILER_FLAGS_fact ${SW_USB_FACT_FLAGS} -DI2S_CHANS_DAC=2
-DI2S_CHANS_ADC=0
-DMIN_FREQ=48000
-DMAX_FREQ=48000
-DFACT=1
#-DUSE_EX3D
-DMIXER=0
-DUAC2_MODE=1
#-ldnr_50ms
#-llib_ex3d_all
#-DEQ_EN=1
#-DEX3D_SF_NUM=3
-DNUM_USB_CHAN_OUT=2
-DNUM_USB_CHAN_IN=0
#-DNUM_EX3D_CHAN_OUT=2
-DMIN_VOLUME=0xE000
-DINPUT_VOLUME_CONTROL=0
-DOUTPUT_VOLUME_CONTROL=0
-DDEBUG_MEMORY_LOG_ENABLED=1
-DHID_DFU_EN=1
-DXUA_DFU_EN=1
#-DIR_SWITCHING_MODE
-DHID_CONTROLS=1)
set(APP_COMPILER_FLAGS_f1_music_uac2 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
-DI2S_CHANS_ADC=2
-DMIN_FREQ=44100
-DMAX_FREQ=192000
-DF1_MUSIC_UAC2=1
-DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=24
-DSTREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS=24
-DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=24
-DSTREAM_FORMAT_INPUT_2_RESOLUTION_BITS=24
-DINPUT_FORMAT_COUNT=1
-DOUTPUT_FORMAT_COUNT=1
#-DUSE_EX3D
-DMIXER=0
-DUAC2_MODE=1
#-ldnr_50ms
#-llib_ex3d_all
-DEQ_EN=1
#-DEX3D_SF_NUM=3
-DNUM_USB_CHAN_OUT=2
-DNUM_USB_CHAN_IN=2
#-DNUM_EX3D_CHAN_OUT=2
-DMIN_VOLUME=0xE000
-DINPUT_VOLUME_CONTROL=1
-DOUTPUT_VOLUME_CONTROL=1
#-DDEBUG_MEMORY_LOG_ENABLED=1
-DXUA_DFU_EN=1
-DHID_DFU_EN=1
#-DIR_SWITCHING_MODE
-DHID_CONTROLS=1)
set(APP_COMPILER_FLAGS_f3_f4_fps_uac2 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
-DI2S_CHANS_ADC=2
-DMIN_FREQ=48000
-DMAX_FREQ=48000
-DUSE_EX3D=1
-DF3_F4_FPS_UAC2=1
-DMIXER=0
-DUAC2_MODE=1
-ldnr_50ms
-llib_ex3d_all
-DEQ_EN=1
-DDNR_ENABLE=1
-DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=16
-DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=16
-DINPUT_FORMAT_COUNT=1
-DOUTPUT_FORMAT_COUNT=1
-DEX3D_SF_NUM=3
-DNUM_USB_CHAN_OUT=8
-DNUM_USB_CHAN_IN=2
-DNUM_EX3D_CHAN_OUT=2
-DMIN_VOLUME=0xE000
-DINPUT_VOLUME_CONTROL=1
-DOUTPUT_VOLUME_CONTROL=1
#-DDEBUG_MEMORY_LOG_ENABLED=1
-DXUA_DFU_EN=1
-DHID_DFU_EN=1
-DIR_SWITCHING_MODE
-DHID_CONTROLS=1)
set(APP_COMPILER_FLAGS_f6_f7_fps_uac1 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
-DI2S_CHANS_ADC=2
-DAUDIO_CLASS=1
-DMIN_FREQ=48000
-DMAX_FREQ=48000
-DMCLK_441=512*44100
-DMCLK_48=512*48000
-DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=16
-DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=16
-DINPUT_FORMAT_COUNT=1
-DOUTPUT_FORMAT_COUNT=1
-DUAC1_MODE=1
-DUSE_EX3D=1
-DF6_F7_FPS_UAC1=1
-DMIXER=0
-ldnr_50ms
-DDNR_ENABLE=1
-llib_ex3d_all
-DEQ_EN=1
-DEX3D_SF_NUM=3
-DNUM_USB_CHAN_OUT=8
-DNUM_USB_CHAN_IN=2
-DNUM_EX3D_CHAN_OUT=2
-DMIN_VOLUME=0xE000
-DINPUT_VOLUME_CONTROL=1
-DOUTPUT_VOLUME_CONTROL=1
#-DDEBUG_MEMORY_LOG_ENABLED=1
-DXUA_DFU_EN=1
-DHID_DFU_EN=1
-DHID_CONTROLS_UAC1=1
-DIR_SWITCHING_MODE
-DHID_CONTROLS=1)
set(APP_INCLUDES src src/core src/extensions ../../lib_dnr/lib_dnr)
set(XMOS_SANDBOX_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
XMOS_REGISTER_APP()
###=========================================================================###
# Flash image generation
# Slot assignment (matches MODE_Fxx flag values in audiohw.xc):
# slot 1 = f3_f4_fps_uac2 (COAX_IN_FLAG = MODE_F3_F4_FPS_UAC2)
# slot 2 = f5_music_uac1 (UAC1_IN_FLAG = MODE_F5_MUSIC_UAC1) <- factory base
# slot 3 = f1_music_uac2 (OPT_IN_FLAG = MODE_F1_MUSIC_UAC2)
# slot 4 = f6_f7_fps_uac1 (USB_IN_FLAG = MODE_F6_F7_FPS_UAC1)
###=========================================================================###
set(APP_BIN_DIR ${CMAKE_CURRENT_LIST_DIR}/bin)
set(APP_BASE ${PROJECT_NAME})
set(XE_FACT ${APP_BIN_DIR}/fact/${APP_BASE}_fact.xe)
set(XE_F1 ${APP_BIN_DIR}/f1_music_uac2/${APP_BASE}_f1_music_uac2.xe)
set(XE_F3F4 ${APP_BIN_DIR}/f3_f4_fps_uac2/${APP_BASE}_f3_f4_fps_uac2.xe)
set(XE_F5 ${APP_BIN_DIR}/f5_music_uac1/${APP_BASE}_f5_music_uac1.xe)
set(XE_F6F7 ${APP_BIN_DIR}/f6_f7_fps_uac1/${APP_BASE}_f6_f7_fps_uac1.xe)
set(LOADER_OBJ ${CMAKE_CURRENT_LIST_DIR}/loader.o)
set(TARGET_XN ${CMAKE_CURRENT_LIST_DIR}/src/core/synido.xn)
# factory_<project>_<version>.bin — full factory image (base + 4 upgrade slots)
add_custom_target(factory_bin
COMMAND ${CMAKE_COMMAND} -E echo "xflash ${XE_FACT} --loader ${LOADER_OBJ} --upgrade 1 ${XE_F3F4} --upgrade 2 ${XE_F5} --upgrade 3 ${XE_F1} --upgrade 4 ${XE_F6F7} -o ${CMAKE_CURRENT_LIST_DIR}/factory_${APP_BASE}_${FW_VERSION}.bin"
COMMAND xflash ${XE_FACT} --loader ${LOADER_OBJ}
--upgrade 2 ${XE_F5}
--upgrade 3 ${XE_F1}
--upgrade 1 ${XE_F3F4}
--upgrade 4 ${XE_F6F7}
-o ${CMAKE_CURRENT_LIST_DIR}/factory_${APP_BASE}_${FW_VERSION}.bin
#DEPENDS f1_music_uac2 f3_f4_fps_uac2 f5_music_uac1 f6_f7_fps_uac1
COMMENT "Generating factory image: factory_${APP_BASE}_${FW_VERSION}.bin"
VERBATIM
)
# update_<project>_<version>.bin — DFU upgrade package (upgrade slots only)
add_custom_target(update_bin
COMMAND ${CMAKE_COMMAND} -E echo "xflash --factory-version 15.2 --target-file ${TARGET_XN} --upgrade 1 ${XE_F3F4} --upgrade 2 ${XE_F5} --upgrade 3 ${XE_F1} --upgrade 4 ${XE_F6F7} -o ${CMAKE_CURRENT_LIST_DIR}/update_${APP_BASE}_${FW_VERSION}.bin"
COMMAND xflash --factory-version 15.2 --target-file ${TARGET_XN}
--upgrade 2 ${XE_F5}
--upgrade 3 ${XE_F1}
--upgrade 1 ${XE_F3F4}
--upgrade 4 ${XE_F6F7}
-o ${CMAKE_CURRENT_LIST_DIR}/update_${APP_BASE}_${FW_VERSION}.bin
#DEPENDS f1_music_uac2 f3_f4_fps_uac2 f5_music_uac1 f6_f7_fps_uac1
COMMENT "Generating update image: update_${APP_BASE}_${FW_VERSION}.bin"
VERBATIM
)

View File

@@ -1,3 +0,0 @@
xflash bin/fact/app_usb_aud_sy102_fact.xe --loader loader.o --upgrade 2 bin/f5_music_uac1/app_usb_aud_sy102_f5_music_uac1.xe --upgrade 3 bin/f1_music_uac2/app_usb_aud_sy102_f1_music_uac2.xe --upgrade 1 bin/f3_f4_fps_uac2/app_usb_aud_sy102_f3_f4_fps_uac2.xe --upgrade 4 bin/f6_f7_fps_uac1/app_usb_aud_sy102_f6_f7_fps_uac1.xe -o %1
rem --upgrade 4 bin/f6_f7_fps_uac1/app_usb_aud_sy102_f6_f7_fps_uac1.xe

View File

@@ -1 +0,0 @@
xflash --factory-version 15.3 --target-file src/core/synido.xn --upgrade 2 bin/f5_music_uac1/app_usb_aud_sy102_f5_music_uac1.xe --upgrade 3 bin/f1_music_uac2/app_usb_aud_sy102_f1_music_uac2.xe --upgrade 1 bin/f3_f4_fps_uac2/app_usb_aud_sy102_f3_f4_fps_uac2.xe --upgrade 4 bin/f6_f7_fps_uac1/app_usb_aud_sy102_f6_f7_fps_uac1.xe -o %1

View File

@@ -1,89 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Network xmlns="http://www.xmos.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.xmos.com http://www.xmos.com">
<Type>Board</Type>
<Name>xcore.ai MC Audio Board</Name>
<Declarations>
<Declaration>tileref tile[2]</Declaration>
</Declarations>
<Packages>
<Package id="0" Type="XS3-UnA-1024-TQ128">
<Nodes>
<Node Id="0" InPackageId="0" Type="XS3-L16A-1024" Oscillator="24MHz" SystemFrequency="600MHz" ReferenceFrequency="100MHz">
<Boot>
<Source Location="bootFlash"/>
</Boot>
<Tile Number="0" Reference="tile[0]">
<Port Location="XS1_PORT_1B" Name="PORT_SQI_CS"/>
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK"/>
<Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO"/>
<!-- I2C -->
<Port Location="XS1_PORT_1P" Name="PORT_I2C_SCL"/> <!-- orig 1L, Synido 1P -->
<Port Location="XS1_PORT_1O" Name="PORT_I2C_SDA"/> <!-- orig 1M, Synido 1O -->
<!-- HRT3236 -->
<Port Location="XS1_PORT_1N" Name="PORT_HTR3236_SDB"/>
<!-- Mic Encoder -->
<Port Location="XS1_PORT_4F" Name="PORT_MIC_GAIN_ENCODER1"/> <!-- 4F1: FOOTSTEPS ENHANCEMENT; 4F2: MIC_GAIN_ENCODER_INPUT_1; 4F3: MIC MUTE -->
<Port Location="XS1_PORT_4E" Name="PORT_MIC_GAIN_ENCODER2"/> <!-- 4E2: MIC_GAIN_ENCODER_INPUT_2; 4E3: AI DENOISE ONOFF -->
<!-- HP Encoder -->
<Port Location="XS1_PORT_8D" Name="PORT_HP_GAIN_ENCODER"/> <!-- 8D4: HP_GAIN_ENCODER_INPUT_1; 8D5: HP_GAIN_ENCODER_INPUT_2; 8D6: HP MUTE -->
<!-- Buttons -->
<Port Location="XS1_PORT_1A" Name="PORT_BUTTON_MUSIC_MODE"/>
<Port Location="XS1_PORT_1M" Name="PORT_BUTTON_GAME_MODE"/>
<Port Location="XS1_PORT_1L" Name="PORT_BUTTON_AI71_ONOFF"/>
<!-- Clocking -->
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT"/>
<Port Location="XS1_PORT_1D" Name="PORT_MCLK_IN_USB"/>
</Tile>
<Tile Number="1" Reference="tile[1]">
<!-- Audio Ports: I2S -->
<Port Location="XS1_PORT_1D" Name="PORT_MCLK_IN"/>
<Port Location="XS1_PORT_16B" Name="PORT_MCLK_COUNT_2"/>
<Port Location="XS1_PORT_1B" Name="PORT_I2S_LRCLK"/>
<Port Location="XS1_PORT_1C" Name="PORT_I2S_BCLK"/>
<Port Location="XS1_PORT_1K" Name="PORT_I2S_DAC0"/> <!-- orig 1P, Synido 1K -->
<Port Location="XS1_PORT_1A" Name="PORT_I2S_ADC0"/> <!-- orig 1I, Synido 1A -->
<Port Location="XS1_PORT_4A" Name="PORT_CTL_MUTE"/> <!-- Tile1 4D0 -->
<Port Location="XS1_PORT_4D" Name="PORT_CTL_DET"/> <!-- Tile1 4D0 -->
</Tile>
</Node>
</Nodes>
</Package>
</Packages>
<!--
<Nodes>
<Node Id="2" Type="device:" RoutingId="0x8000">
<Service Id="0" Proto="xscope_host_data(chanend c);">
<Chanend Identifier="c" end="3"/>
</Service>
</Node>
</Nodes>
<Links>
<Link Encoding="2wire" Delays="5clk" Flags="XSCOPE">
<LinkEndpoint NodeId="0" Link="XL0"/>
<LinkEndpoint NodeId="2" Chanend="1"/>
</Link>
</Links>
-->
<ExternalDevices>
<Device NodeId="0" Tile="0" Class="SQIFlash" Name="bootFlash" PageSize="256" SectorSize="4096" NumPages="16384">
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS"/>
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK"/>
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO"/>
</Device>
</ExternalDevices>
<JTAGChain>
<JTAGDevice NodeId="0"/>
</JTAGChain>
</Network>