add app_usb_aud_phaten_golden_6ch
This commit is contained in:
224
sw_usb_audio/app_usb_aud_phaten_golden_6ch/CMakeLists.txt
Normal file
224
sw_usb_audio/app_usb_aud_phaten_golden_6ch/CMakeLists.txt
Normal file
@@ -0,0 +1,224 @@
|
||||
cmake_minimum_required(VERSION 3.21)
|
||||
include($ENV{XMOS_CMAKE_PATH}/xcommon.cmake)
|
||||
project(app_usb_aud_phaten_gs)
|
||||
|
||||
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()
|
||||
|
||||
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=1
|
||||
-DBCD_DEVICE_M=0
|
||||
-DBCD_DEVICE_N=0
|
||||
-D${CODEC_IC}
|
||||
-DWINDOWS_OS_DESCRIPTOR_SUPPORT
|
||||
-DDEBUG_PRINT_ENABLE=0)
|
||||
|
||||
|
||||
LINK_DIRECTORIES(${CMAKE_CURRENT_LIST_DIR}/../../lib_dnr/lib_dnr)
|
||||
|
||||
set(APP_COMPILER_FLAGS_ex3d_UAC1 ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
|
||||
-DI2S_CHANS_ADC=0
|
||||
-DAUDIO_CLASS=1
|
||||
-DMIN_FREQ=48000
|
||||
-DMAX_FREQ=48000
|
||||
-DUSE_EX3D
|
||||
-DMIXER=0
|
||||
-DAIZIP_DNR=0 #-ldnr_50ms
|
||||
-llib_ex3d_stereo_2k
|
||||
-DNUM_USB_CHAN_OUT=2
|
||||
-DNUM_USB_CHAN_OUT_FS=2
|
||||
-DNUM_USB_CHAN_IN=0
|
||||
-DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=16
|
||||
-DSTREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS=16
|
||||
-DSTREAM_FORMAT_OUTPUT_3_RESOLUTION_BITS=16
|
||||
-DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=16
|
||||
-DSTREAM_FORMAT_INPUT_2_RESOLUTION_BITS=16
|
||||
-DSTREAM_FORMAT_INPUT_3_RESOLUTION_BITS=16
|
||||
-DNUM_EX3D_CHAN_OUT=2
|
||||
-DINPUT_VOLUME_CONTROL=0
|
||||
-DUAC1_MODE=1
|
||||
-DOUTPUT_VOLUME_CONTROL=0
|
||||
-DXUA_DFU_EN=0
|
||||
-DSTEREO_2K
|
||||
-DHID_CONTROLS=0)
|
||||
|
||||
|
||||
#set(APP_COMPILER_FLAGS_ex3d_stereo_2k ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
|
||||
# -DI2S_CHANS_ADC=2
|
||||
# #-DAUDIO_CLASS=1
|
||||
# -DMIN_FREQ=48000
|
||||
# -DMAX_FREQ=48000
|
||||
# -DUSE_EX3D
|
||||
# -DMIXER=0
|
||||
# -DAIZIP_DNR=0 #-ldnr_50ms
|
||||
# -llib_ex3d_stereo_2k
|
||||
# -DNUM_USB_CHAN_OUT=2
|
||||
# -DNUM_USB_CHAN_IN=2
|
||||
# -DEQ_EN=1
|
||||
# -DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=16
|
||||
# -DSTREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS=16
|
||||
# -DSTREAM_FORMAT_OUTPUT_3_RESOLUTION_BITS=16
|
||||
# -DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=16
|
||||
# -DSTREAM_FORMAT_INPUT_2_RESOLUTION_BITS=16
|
||||
# -DSTREAM_FORMAT_INPUT_3_RESOLUTION_BITS=16
|
||||
# -DNUM_EX3D_CHAN_OUT=2
|
||||
# -DINPUT_VOLUME_CONTROL=1
|
||||
# -DOUTPUT_VOLUME_CONTROL=1
|
||||
# -DXUA_DFU_EN=1
|
||||
# -DSTEREO_2K
|
||||
# -DHID_CONTROLS=1)
|
||||
#
|
||||
#set(APP_COMPILER_FLAGS_ex3d_stereo_8k ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
|
||||
# -DI2S_CHANS_ADC=0
|
||||
# -DMIN_FREQ=48000
|
||||
# -DMAX_FREQ=48000
|
||||
# -DUSE_EX3D
|
||||
# -DMIXER=0
|
||||
# -DAIZIP_DNR=0 #-ldnr_50ms
|
||||
# -llib_ex3d_stereo_8k
|
||||
# -DNUM_USB_CHAN_OUT=2
|
||||
# -DNUM_USB_CHAN_IN=2
|
||||
# -DSTREAM_FORMAT_OUTPUT_1_RESOLUTION_BITS=16
|
||||
# -DSTREAM_FORMAT_OUTPUT_2_RESOLUTION_BITS=16
|
||||
# -DSTREAM_FORMAT_OUTPUT_3_RESOLUTION_BITS=16
|
||||
# -DSTREAM_FORMAT_INPUT_1_RESOLUTION_BITS=16
|
||||
# -DSTREAM_FORMAT_INPUT_2_RESOLUTION_BITS=16
|
||||
# -DSTREAM_FORMAT_INPUT_3_RESOLUTION_BITS=16
|
||||
# -DNUM_EX3D_CHAN_OUT=2
|
||||
# -DXUA_DFU_EN=1
|
||||
# -DINPUT_VOLUME_CONTROL=1
|
||||
# -DOUTPUT_VOLUME_CONTROL=1
|
||||
# -DSTEREO_8K
|
||||
# -DHID_CONTROLS=1)
|
||||
|
||||
|
||||
## IR switching mode
|
||||
set(APP_COMPILER_FLAGS_ex3d_71_all ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
|
||||
-DI2S_CHANS_ADC=2
|
||||
-DMIN_FREQ=48000
|
||||
-DMAX_FREQ=48000
|
||||
-DUSE_EX3D
|
||||
-DMIXER=0
|
||||
-ldnr_50ms
|
||||
-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
|
||||
-DIR_SWITCHING_MODE
|
||||
-DHID_CONTROLS=1)
|
||||
set(APP_COMPILER_FLAGS_ex3d_71_game ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
|
||||
-DI2S_CHANS_ADC=2
|
||||
-DMIN_FREQ=48000
|
||||
-DMAX_FREQ=48000
|
||||
-DUSE_EX3D
|
||||
-DMIXER=0
|
||||
-DAIZIP_DNR=0 #-ldnr_50ms
|
||||
-llib_ex3d_game
|
||||
-DEQ_EN=1
|
||||
-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
|
||||
-DSPATIAL_GAME
|
||||
-DHID_CONTROLS=1)
|
||||
|
||||
set(APP_COMPILER_FLAGS_ex3d_71_music ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
|
||||
-DI2S_CHANS_ADC=2
|
||||
-DMIN_FREQ=48000
|
||||
-DMAX_FREQ=48000
|
||||
-DUSE_EX3D
|
||||
-DMIXER=0
|
||||
-DAIZIP_DNR=0 #-ldnr_50ms
|
||||
-llib_ex3d_music
|
||||
-DNUM_USB_CHAN_OUT=8
|
||||
-DNUM_USB_CHAN_IN=2
|
||||
-DNUM_EX3D_CHAN_OUT=2
|
||||
-DMIN_VOLUME=0xE000
|
||||
-DSPATIAL_MUSIC
|
||||
-DHID_CONTROLS=1)
|
||||
|
||||
set(APP_COMPILER_FLAGS_ex3d_71_movie ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
|
||||
-DI2S_CHANS_ADC=2
|
||||
-DMIN_FREQ=48000
|
||||
-DMAX_FREQ=48000
|
||||
-DUSE_EX3D
|
||||
-DMIXER=0
|
||||
-DAIZIP_DNR=0 #-ldnr_50ms
|
||||
-DEQ_EN=1
|
||||
-llib_ex3d_movie
|
||||
-DNUM_USB_CHAN_OUT=8
|
||||
-DNUM_USB_CHAN_IN=2
|
||||
-DNUM_EX3D_CHAN_OUT=2
|
||||
-DMIN_VOLUME=0xE000
|
||||
-DXUA_DFU_EN=1
|
||||
-DSPATIAL_MOVIE
|
||||
-DHID_CONTROLS=1)
|
||||
|
||||
set(APP_COMPILER_FLAGS_ex3d_71_drama ${SW_USB_AUDIO_FLAGS} -DI2S_CHANS_DAC=2
|
||||
-DI2S_CHANS_ADC=2
|
||||
-DMIN_FREQ=48000
|
||||
-DMAX_FREQ=48000
|
||||
-DUSE_EX3D
|
||||
-DMIXER=0
|
||||
-DAIZIP_DNR=0 #-ldnr_50ms
|
||||
-llib_ex3d_drama
|
||||
-DNUM_USB_CHAN_OUT=8
|
||||
-DNUM_USB_CHAN_IN=2
|
||||
-DNUM_EX3D_CHAN_OUT=2
|
||||
-DMIN_VOLUME=0xE000
|
||||
-DSPATIAL_DRAMA
|
||||
-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()
|
||||
@@ -0,0 +1 @@
|
||||
xflash bin/factory/fact.xe --loader loader.o --upgrade 2 bin\ex3d_UAC1\app_usb_aud_phaten_gs_ex3d_UAC1.xe --upgrade 4 bin/ex3d_stereo_2k/app_usb_aud_phaten_gs_ex3d_stereo_2k.xe --upgrade 1 bin\ex3d_71_game\app_usb_aud_phaten_gs_ex3d_71_game.xe --upgrade 3 bin\ex3d_71_movie\app_usb_aud_phaten_gs_ex3d_71_movie.xe -o %1
|
||||
@@ -0,0 +1,2 @@
|
||||
xflash --factory-version 15.3 --target-file src/core/synido.xn --upgrade 2 bin\ex3d_UAC1\app_usb_aud_phaten_gs_ex3d_UAC1.xe --upgrade 4 bin/ex3d_stereo_2k/app_usb_aud_phaten_gs_ex3d_stereo_2k.xe --upgrade 1 bin\ex3d_71_game\app_usb_aud_phaten_gs_ex3d_71_game.xe --upgrade 3 bin\ex3d_71_movie\app_usb_aud_phaten_gs_ex3d_71_movie.xe -o %1
|
||||
|
||||
BIN
sw_usb_audio/app_usb_aud_phaten_golden_6ch/loader.o
Normal file
BIN
sw_usb_audio/app_usb_aud_phaten_golden_6ch/loader.o
Normal file
Binary file not shown.
BIN
sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/.DS_Store
vendored
Normal file
BIN
sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/.DS_Store
vendored
Normal file
Binary file not shown.
@@ -0,0 +1,91 @@
|
||||
<?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">
|
||||
<Declarations>
|
||||
<Declaration>tileref tile[2]</Declaration>
|
||||
<Declaration>tileref usb_tile</Declaration>
|
||||
</Declarations>
|
||||
|
||||
<Packages>
|
||||
<Package id="0" Type="XS3-UnA-1024-QF60A">
|
||||
<Nodes>
|
||||
<!-- Note that this clock setting is overridden by the app by writing directly to the PLL -->
|
||||
<Node Id="0" InPackageId="0" Type="XS3-L16A-1024" SystemFrequency="600MHz" Oscillator="24MHz" referencefrequency="100MHz">
|
||||
<Boot>
|
||||
<Source Location="bootFlash"/>
|
||||
</Boot>
|
||||
<!-- <Extmem sizeMbit="1024" Frequency="175MHz">
|
||||
<Padctrl clk="0x0" cke="0x0" cs_n="0x0" we_n="0x0" cas_n="0x0" ras_n="0x0" addr="0x0" ba="0x0" dq="0x0" dqs="0x0" dm="0x0"/>
|
||||
<Lpddr lmr_opcode="0x0" emr_opcode="0x0"/>
|
||||
</Extmem> -->
|
||||
<Tile Number="0" Reference="tile[0]">
|
||||
<!-- QSPI ports -->
|
||||
<Port Location="XS1_PORT_1B" Name="PORT_SQI_CS_0"/>
|
||||
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK_0"/>
|
||||
<Port Location="XS1_PORT_4B" Name="PORT_SQI_SIO_0"/>
|
||||
|
||||
<!-- SPI ports -->
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_SSB"/>
|
||||
<Port Location="XS1_PORT_1C" Name="PORT_SQI_SCLK_0"/>
|
||||
<Port Location="XS1_PORT_1D" Name="PORT_SPI_MOSI"/>
|
||||
<Port Location="XS1_PORT_1P" Name="PORT_SPI_MISO"/>
|
||||
|
||||
<!-- I2C ports -->
|
||||
<Port Location="XS1_PORT_1N" Name="PORT_I2C_SCL"/>
|
||||
<Port Location="XS1_PORT_1O" Name="PORT_I2C_SDA"/>
|
||||
|
||||
<!-- GPIO ports -->
|
||||
<Port Location="XS1_PORT_8C" Name="PORT_GPO"/>
|
||||
<Port Location="XS1_PORT_8D" Name="PORT_GPI"/>
|
||||
<Port Location="XS1_PORT_1P" Name="PORT_ADC_RST"/>
|
||||
|
||||
<!-- Used for keeping XUA happy only -->
|
||||
<Port Location="XS1_PORT_1G" Name="PORT_NOT_IN_PACKAGE_0"/>
|
||||
|
||||
<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]">
|
||||
|
||||
<!-- MIC related ports -->
|
||||
<Port Location="XS1_PORT_1G" Name="PORT_PDM_CLK"/>
|
||||
<Port Location="XS1_PORT_1F" Name="PORT_PDM_DATA"/>
|
||||
|
||||
<!-- Audio ports -->
|
||||
<Port Location="XS1_PORT_1D" Name="PORT_MCLK_IN"/>
|
||||
<Port Location="XS1_PORT_1C" Name="PORT_I2S_BCLK"/>
|
||||
<Port Location="XS1_PORT_1B" Name="PORT_I2S_LRCLK"/>
|
||||
<Port Location="XS1_PORT_1K" Name="PORT_I2S_ADC0"/>
|
||||
<Port Location="XS1_PORT_1A" Name="PORT_I2S_DAC0"/>
|
||||
</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">
|
||||
<Attribute Name="PORT_SQI_CS" Value="PORT_SQI_CS_0"/>
|
||||
<Attribute Name="PORT_SQI_SCLK" Value="PORT_SQI_SCLK_0"/>
|
||||
<Attribute Name="PORT_SQI_SIO" Value="PORT_SQI_SIO_0"/>
|
||||
</Device>
|
||||
</ExternalDevices>
|
||||
<JTAGChain>
|
||||
<JTAGDevice NodeId="0"/>
|
||||
</JTAGChain>
|
||||
|
||||
</Network>
|
||||
@@ -0,0 +1,88 @@
|
||||
<?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_1L" Name="PORT_BUTTON_GAME_MODE"/>
|
||||
<Port Location="XS1_PORT_1M" 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_4D" Name="PORT_CTL_MUTE"/> <!-- 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>
|
||||
347
sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/core/xua_conf.h
Normal file
347
sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/core/xua_conf.h
Normal file
@@ -0,0 +1,347 @@
|
||||
/**
|
||||
* @file xua_conf.h
|
||||
* @brief Defines relating to device configuration and customisation.
|
||||
* For xCORE.ai Audio MC Board
|
||||
* @author Ross Owen, XMOS Limited
|
||||
*/
|
||||
#ifndef _XUA_CONF_H_
|
||||
#define _XUA_CONF_H_
|
||||
|
||||
#include "../../../shared/version.h"
|
||||
|
||||
/*
|
||||
* Device configuration option defines to override default defines found in lib_xua/api/xua_conf_default.h
|
||||
*
|
||||
* Build can be customised but changing and adding defines here
|
||||
*
|
||||
* Note, we check if they are already defined in Makefile
|
||||
*/
|
||||
|
||||
/*** Defines relating to basic functionality ***/
|
||||
/* Enable/Disable MIDI - Default is MIDI off */
|
||||
#ifndef MIDI
|
||||
#define MIDI (0)
|
||||
#endif
|
||||
|
||||
/* Enable/Disable S/PDIF output - Default is S/PDIF off */
|
||||
#ifndef XUA_SPDIF_TX_EN
|
||||
#define XUA_SPDIF_TX_EN (0)
|
||||
#endif
|
||||
|
||||
/* Enable/Disable S/PDIF input - Default is S/PDIF off */
|
||||
#ifndef XUA_SPDIF_RX_EN
|
||||
#define XUA_SPDIF_RX_EN (0)
|
||||
#endif
|
||||
|
||||
/* Enable/Disable ADAT output - Default is ADAT off */
|
||||
#ifndef XUA_ADAT_TX_EN
|
||||
#define XUA_ADAT_TX_EN (0)
|
||||
#endif
|
||||
|
||||
/* Enable/Disable ADAT input - Default is ADAT off */
|
||||
#ifndef XUA_ADAT_RX_EN
|
||||
#define XUA_ADAT_RX_EN (0)
|
||||
#endif
|
||||
|
||||
/* Enable/Disable Mixing core(s) - Default is on */
|
||||
#ifndef MIXER
|
||||
#define MIXER (0)
|
||||
#endif
|
||||
|
||||
#ifndef _XUA_BMAX_POWER
|
||||
#define _XUA_BMAX_POWER (50)
|
||||
#endif
|
||||
|
||||
/* Set the number of mixes to perform - Default is 0 i.e mixing disabled */
|
||||
#ifndef MAX_MIX_COUNT
|
||||
#define MAX_MIX_COUNT (0)
|
||||
#endif
|
||||
|
||||
/* Audio Class version - Default is 2.0 */
|
||||
#ifndef AUDIO_CLASS
|
||||
#define AUDIO_CLASS (2)
|
||||
#endif
|
||||
|
||||
/*** Defines relating to channel counts ***/
|
||||
/* Number of I2S channels to DACs*/
|
||||
#ifndef I2S_CHANS_DAC
|
||||
#define I2S_CHANS_DAC (8)
|
||||
#endif
|
||||
|
||||
/* Number of I2S channels from ADCs */
|
||||
#ifndef I2S_CHANS_ADC
|
||||
#define I2S_CHANS_ADC (8)
|
||||
#endif
|
||||
|
||||
/* Number of USB streaming channels - by default calculate by counting audio interfaces */
|
||||
#ifndef NUM_USB_CHAN_IN
|
||||
#define NUM_USB_CHAN_IN (I2S_CHANS_ADC + 2*XUA_SPDIF_RX_EN + 8*XUA_ADAT_RX_EN) /* Device to Host */
|
||||
#endif
|
||||
|
||||
#ifndef NUM_USB_CHAN_OUT
|
||||
#define NUM_USB_CHAN_OUT (I2S_CHANS_DAC + 2*XUA_SPDIF_TX_EN + 8*XUA_ADAT_TX_EN) /* Host to Device */
|
||||
#endif
|
||||
|
||||
/*** Defines relating to channel arrangement/indices ***/
|
||||
/* Channel index of S/PDIF Tx channels: separate channels after analogue channels (if they fit) */
|
||||
#ifndef SPDIF_TX_INDEX
|
||||
#if (I2S_CHANS_DAC + 2*XUA_SPDIF_TX_EN) <= NUM_USB_CHAN_OUT
|
||||
#define SPDIF_TX_INDEX (I2S_CHANS_DAC)
|
||||
#else
|
||||
#define SPDIF_TX_INDEX (0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Channel index of S/PDIF Rx channels: separate channels after analogue channels */
|
||||
#ifndef SPDIF_RX_INDEX
|
||||
#define SPDIF_RX_INDEX (I2S_CHANS_ADC)
|
||||
#endif
|
||||
|
||||
/* Channel index of ADAT Tx channels: separate channels after S/PDIF channels (if they fit) */
|
||||
#ifndef ADAT_TX_INDEX
|
||||
#define ADAT_TX_INDEX (I2S_CHANS_DAC + 2*XUA_SPDIF_TX_EN)
|
||||
#endif
|
||||
|
||||
/* Channel index of ADAT Rx channels: separate channels after S/PDIF channels */
|
||||
#ifndef ADAT_RX_INDEX
|
||||
#define ADAT_RX_INDEX (I2S_CHANS_ADC + 2*XUA_SPDIF_RX_EN)
|
||||
#endif
|
||||
|
||||
/*** Defines relating to audio frequencies ***/
|
||||
/* Master clock defines (in Hz) */
|
||||
#ifndef MCLK_441
|
||||
#define MCLK_441 (256*44100) /* 44.1, 88.2 etc */
|
||||
#endif
|
||||
|
||||
#ifndef MCLK_48
|
||||
#define MCLK_48 (256*48000) /* 48, 96 etc */
|
||||
#endif
|
||||
|
||||
/* Minumum sample frequency device runs at */
|
||||
#ifndef MIN_FREQ
|
||||
#define MIN_FREQ (48000) //(44100)
|
||||
#endif
|
||||
|
||||
/* Maximum sample frequency device runs at */
|
||||
#ifndef MAX_FREQ
|
||||
#define MAX_FREQ (48000)
|
||||
#endif
|
||||
|
||||
/*** Defines relating to feature placement regarding tiles ***/
|
||||
#define XUD_TILE (0)
|
||||
#define PLL_REF_TILE (0)
|
||||
|
||||
#define AUDIO_IO_TILE (1)
|
||||
#define MIDI_TILE (1)
|
||||
|
||||
/*** Defines relating to USB descriptor strings and ID's ***/
|
||||
#define VENDOR_ID (0x20B1) /* XMOS Vendor ID*/
|
||||
#ifndef PID_AUDIO_2
|
||||
#if defined (STEREO_2K)
|
||||
#define PID_AUDIO_2 (0x0017)
|
||||
#elif defined (SPATIAL_MOVIE)
|
||||
#define PID_AUDIO_2 (0x0018)
|
||||
#else
|
||||
#define PID_AUDIO_2 (0x0016)
|
||||
#endif
|
||||
#endif
|
||||
#ifndef PID_AUDIO_1
|
||||
#define PID_AUDIO_1 (0x0017)
|
||||
#endif
|
||||
|
||||
|
||||
#define PRODUCT_STR_A2 "XMOS True AI7.1"
|
||||
#define PRODUCT_STR_A1 "XMOS True AI7.1"
|
||||
|
||||
/* Board power source - Default is bus-powered */
|
||||
#ifndef XUA_POWERMODE
|
||||
#define XUA_POWERMODE XUA_POWERMODE_BUS
|
||||
#endif
|
||||
|
||||
/* Enable/Disable example HID code - Default is off */
|
||||
#ifndef HID_CONTROLS
|
||||
#define HID_CONTROLS (0)
|
||||
#endif
|
||||
|
||||
#define EXCLUDE_USB_AUDIO_MAIN (1)
|
||||
/*
|
||||
* New spispec for QF60 board
|
||||
* */
|
||||
|
||||
#define FL_QUADDEVICE_XT25F16F \
|
||||
{ \
|
||||
0, /* XT25F16F - Just specify 0 as flash_id */ \
|
||||
256, /* page size */ \
|
||||
8192, /* num pages */ \
|
||||
3, /* address size */ \
|
||||
4, /* log2 clock divider */ \
|
||||
0x9F, /* QSPI_RDID */ \
|
||||
0, /* id dummy bytes */ \
|
||||
3, /* id size in bytes */ \
|
||||
0x0B4015, /* device id */ \
|
||||
0x20, /* QSPI_SE */ \
|
||||
4096, /* Sector erase is always 4KB */ \
|
||||
0x06, /* QSPI_WREN */ \
|
||||
0x04, /* QSPI_WRDI */ \
|
||||
PROT_TYPE_SR, /* Protection via SR */ \
|
||||
{{0x0,0x00},{0,0}}, /* QSPI_SP, QSPI_SU */ \
|
||||
0x02, /* QSPI_PP */ \
|
||||
0xEB, /* QSPI_READ_FAST */ \
|
||||
1, /* 1 read dummy byte */ \
|
||||
SECTOR_LAYOUT_REGULAR, /* mad sectors */ \
|
||||
{4096,{0,{0}}}, /* regular sector sizes */ \
|
||||
0x05, /* QSPI_RDSR */ \
|
||||
0x01, /* QSPI_WRSR */ \
|
||||
0x01, /* QSPI_WIP_BIT_MASK */ \
|
||||
}
|
||||
|
||||
#define FL_QUADDEVICE_WINBOND_W25Q16JW \
|
||||
{ \
|
||||
0, /* W25Q16JW - Just specify 0 as flash_id */ \
|
||||
256, /* page size */ \
|
||||
8192, /* num pages */ \
|
||||
3, /* address size */ \
|
||||
4, /* log2 clock divider */ \
|
||||
0x9F, /* QSPI_RDID */ \
|
||||
0, /* id dummy bytes */ \
|
||||
3, /* id size in bytes */ \
|
||||
0xEF4015, /* device id */ \
|
||||
0x20, /* QSPI_SE */ \
|
||||
4096, /* Sector erase is always 4KB */ \
|
||||
0x06, /* QSPI_WREN */ \
|
||||
0x04, /* QSPI_WRDI */ \
|
||||
PROT_TYPE_SR, /* Protection via SR */ \
|
||||
{{0x3C,0x00},{0,0}}, /* QSPI_SP, QSPI_SU */ \
|
||||
0x02, /* QSPI_PP */ \
|
||||
0xEB, /* QSPI_READ_FAST */ \
|
||||
1, /* 1 read dummy byte */ \
|
||||
SECTOR_LAYOUT_REGULAR, /* mad sectors */ \
|
||||
{4096,{0,{0}}}, /* regular sector sizes */ \
|
||||
0x05, /* QSPI_RDSR */ \
|
||||
0x01, /* QSPI_WRSR */ \
|
||||
0x01, /* QSPI_WIP_BIT_MASK */ \
|
||||
}
|
||||
|
||||
#define FL_QUADDEVICE_UC25HQ16B \
|
||||
{ \
|
||||
0, /* W25Q16JW - Just specify 0 as flash_id */ \
|
||||
256, /* page size */ \
|
||||
8192, /* num pages */ \
|
||||
3, /* address size */ \
|
||||
4, /* log2 clock divider */ \
|
||||
0x9F, /* QSPI_RDID */ \
|
||||
0, /* id dummy bytes */ \
|
||||
3, /* id size in bytes */ \
|
||||
0xB36015, /* device id */ \
|
||||
0x20, /* QSPI_SE */ \
|
||||
4096, /* Sector erase is always 4KB */ \
|
||||
0x06, /* QSPI_WREN */ \
|
||||
0x04, /* QSPI_WRDI */ \
|
||||
PROT_TYPE_SR, /* Protection via SR */ \
|
||||
{{0x3C,0x00},{0,0}}, /* QSPI_SP, QSPI_SU */ \
|
||||
0x02, /* QSPI_PP */ \
|
||||
0xEB, /* QSPI_READ_FAST */ \
|
||||
1, /* 1 read dummy byte */ \
|
||||
SECTOR_LAYOUT_REGULAR, /* mad sectors */ \
|
||||
{4096,{0,{0}}}, /* regular sector sizes */ \
|
||||
0x05, /* QSPI_RDSR */ \
|
||||
0x01, /* QSPI_WRSR */ \
|
||||
0x01, /* QSPI_WIP_BIT_MASK */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* New spispec for QF60 3V3 board
|
||||
* */
|
||||
|
||||
#define FL_QUADDEVICE_WINBOND_W25Q32JVxxxM \
|
||||
{ \
|
||||
0, /* W25Q32JV - Just specify 0 as flash_id */ \
|
||||
256, /* page size */ \
|
||||
16384, /* num pages */ \
|
||||
3, /* address size */ \
|
||||
4, /* log2 clock divider */ \
|
||||
0x9F, /* QSPI_RDID */ \
|
||||
0, /* id dummy bytes */ \
|
||||
3, /* id size in bytes */ \
|
||||
0xEF4016, /* device id */ \
|
||||
0x20, /* QSPI_SE */ \
|
||||
4096, /* Sector erase is always 4KB */ \
|
||||
0x06, /* QSPI_WREN */ \
|
||||
0x04, /* QSPI_WRDI */ \
|
||||
PROT_TYPE_SR, /* Protection via SR */ \
|
||||
{{0x3C,0x00},{0,0}}, /* QSPI_SP, QSPI_SU */ \
|
||||
0x02, /* QSPI_PP */ \
|
||||
0xEB, /* QSPI_READ_FAST */ \
|
||||
1, /* 1 read dummy byte */ \
|
||||
SECTOR_LAYOUT_REGULAR, /* mad sectors */ \
|
||||
{4096,{0,{0}}}, /* regular sector sizes */ \
|
||||
0x05, /* QSPI_RDSR */ \
|
||||
0x01, /* QSPI_WRSR */ \
|
||||
0x01, /* QSPI_WIP_BIT_MASK */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* New spispec for xcore-AI explorer board
|
||||
* */
|
||||
#define FL_QUADDEVICE_MX25R3235 \
|
||||
{ \
|
||||
0, /* MX25R3235 - Just specify 0 as flash_id */ \
|
||||
256, /* page size */ \
|
||||
16384, /* num pages */ \
|
||||
3, /* address size */ \
|
||||
3, /* log2 clock divider */ \
|
||||
0x9F, /* QSPI_RDID */ \
|
||||
0, /* id dummy bytes */ \
|
||||
3, /* id size in bytes */ \
|
||||
0xC22816, /* device id */ \
|
||||
0x20, /* QSPI_SE */ \
|
||||
4096, /* Sector erase is always 4KB */ \
|
||||
0x06, /* QSPI_WREN */ \
|
||||
0x04, /* QSPI_WRDI */ \
|
||||
PROT_TYPE_SR, /* Protection via SR */ \
|
||||
{{0x3C,0x00},{0,0}}, /* QSPI_SP, QSPI_SU */ \
|
||||
0x02, /* QSPI_PP */ \
|
||||
0xEB, /* QSPI_READ_FAST */ \
|
||||
1, /* 1 read dummy byte */ \
|
||||
SECTOR_LAYOUT_REGULAR, /* mad sectors */ \
|
||||
{4096,{0,{0}}}, /* regular sector sizes */ \
|
||||
0x05, /* QSPI_RDSR */ \
|
||||
0x01, /* QSPI_WRSR */ \
|
||||
0x01, /* QSPI_WIP_BIT_MASK */ \
|
||||
}
|
||||
|
||||
#define FL_QUADDEVICE_MX25L160E \
|
||||
{ \
|
||||
0, /* MX25R3235 - Just specify 0 as flash_id */ \
|
||||
256, /* page size */ \
|
||||
8192, /* num pages */ \
|
||||
3, /* address size */ \
|
||||
3, /* log2 clock divider */ \
|
||||
0x9F, /* QSPI_RDID */ \
|
||||
0, /* id dummy bytes */ \
|
||||
3, /* id size in bytes */ \
|
||||
0xC22017, /* device id */ \
|
||||
0x20, /* QSPI_SE */ \
|
||||
4096, /* Sector erase is always 4KB */ \
|
||||
0x06, /* QSPI_WREN */ \
|
||||
0x04, /* QSPI_WRDI */ \
|
||||
PROT_TYPE_SR, /* Protection via SR */ \
|
||||
{{0x3C,0x00},{0,0}}, /* QSPI_SP, QSPI_SU */ \
|
||||
0x02, /* QSPI_PP */ \
|
||||
0xEB, /* QSPI_READ_FAST */ \
|
||||
1, /* 1 read dummy byte */ \
|
||||
SECTOR_LAYOUT_REGULAR, /* mad sectors */ \
|
||||
{4096,{0,{0}}}, /* regular sector sizes */ \
|
||||
0x05, /* QSPI_RDSR */ \
|
||||
0x01, /* QSPI_WRSR */ \
|
||||
0x01, /* QSPI_WIP_BIT_MASK */ \
|
||||
}
|
||||
|
||||
|
||||
// DFU_FLASH_DEVICE is a comma-separated list of flash spec structures
|
||||
// This define is used in lib_xua/lib_xua/src/dfu/flashlib_user.c
|
||||
#define DFU_FLASH_DEVICE FL_QUADDEVICE_XT25F16F, FL_QUADDEVICE_WINBOND_W25Q16JW, FL_QUADDEVICE_UC25HQ16B, FL_QUADDEVICE_WINBOND_W25Q32JVxxxM, FL_QUADDEVICE_MX25R3235, FL_QUADDEVICE_MX25L160E
|
||||
//:
|
||||
#include "user_main.h"
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,12 @@
|
||||
#include <print.h>
|
||||
#include "xua.h"
|
||||
|
||||
on tile[XUD_TILE]: in port p_vbus = XS1_PORT_4C;
|
||||
|
||||
unsigned int XUD_HAL_GetVBusState(void)
|
||||
{
|
||||
unsigned vBus;
|
||||
p_vbus :> vBus;
|
||||
return !vBus;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
|
||||
void agc_init_interface(void);
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
#ifndef AZP_H_
|
||||
#define AZP_H_
|
||||
#include "stdint.h"
|
||||
typedef enum
|
||||
{
|
||||
errAZP_NoError = 0,
|
||||
errAZP_NotReady,
|
||||
errAZP_InvalidParam,
|
||||
errAZP_InvalidLicense,
|
||||
errAZP_BufferOverflow,
|
||||
errAZP_BufferTooSmall,
|
||||
}AZP_STATUS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int8_t *buffer1;
|
||||
int8_t *buffer2;
|
||||
int32_t buffer1_size;
|
||||
int32_t buffer2_size;
|
||||
int32_t sample_rate;
|
||||
}azp_dnr_pram_t;
|
||||
|
||||
|
||||
/// @brief DNR initialization
|
||||
/// @param param Configuration parameters
|
||||
/// @return License status
|
||||
/// @brief DNR initialization
|
||||
/// @param param Configuration parameters
|
||||
/// @return License status
|
||||
AZP_STATUS AI_DNR_init(azp_dnr_pram_t *pram);
|
||||
|
||||
/// @brief DNR processing
|
||||
/// @param audio Q31 input and output
|
||||
/// @return License status
|
||||
AZP_STATUS AI_DNR_Processing(int32_t *audio);
|
||||
/// @brief Get version number
|
||||
/// @return If not licensed, returns NULL
|
||||
char * AI_DNR_Version();
|
||||
/// @brief 初始化
|
||||
/// @param buffer 公共区buffer
|
||||
/// @param buf_size 公共区buffer size
|
||||
/// @param buffer2 私有区buffer
|
||||
/// @param buffer2_size 私有区buffer size
|
||||
/// @return
|
||||
//AZP_STATUS azp_dnr_init(int8_t *buffer, int32_t buf_size,int8_t *buffer2,int32_t buffer2_size);
|
||||
/// @brief DNR 处理
|
||||
/// @param audio 32bit Q31 单声道
|
||||
/// @return
|
||||
//AZP_STATUS Aizip_DNR_Processing(int32_t *audio);
|
||||
/// @brief 获取工作buffer大小
|
||||
/// @param buf_size
|
||||
/// @param buf_size2
|
||||
void getBufferSize(int32_t *buf_size, int32_t *buf_size2);/// @brief 设置是否开启EQ ,默认开启
|
||||
/// @param status
|
||||
//void setEQ_Status(int8_t status);
|
||||
/// @brief 设置是否开启AGC ,默认开启
|
||||
/// @param status
|
||||
//void setAGC_Status(int8_t status);
|
||||
/// @brief Set the noise reduction depth
|
||||
/// @param dB Range (-200 to 0 dB)
|
||||
/// -200: Maximum noise reduction
|
||||
/// 0: No noise reduction
|
||||
void setNoisy_mix_factor(float dB);
|
||||
#endif // AZP_H_
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright (c) 2022 XMOS LIMITED. This Software is subject to the terms of the
|
||||
// XMOS Public License: Version 1
|
||||
|
||||
#ifndef AUDIO_PIPELINE_DSP_H_
|
||||
#define AUDIO_PIPELINE_DSP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//#include "agc_api.h"
|
||||
|
||||
|
||||
//typedef struct agc_stage_ctx {
|
||||
// agc_meta_data_t md;
|
||||
// agc_state_t state;
|
||||
//} agc_stage_ctx_t;
|
||||
|
||||
#endif /* AUDIO_PIPELINE_DSP_H_ */
|
||||
1250
sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc
Normal file
1250
sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/audiohw.xc
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,16 @@
|
||||
#include <platform.h>
|
||||
|
||||
//on tile[0]: out port p_leds = XS1_PORT_4F;
|
||||
|
||||
void UserAudioStreamStart(void)
|
||||
{
|
||||
/* Turn all LEDs on */
|
||||
// p_leds <: 0xF;
|
||||
}
|
||||
|
||||
void UserAudioStreamStop(void)
|
||||
{
|
||||
/* Turn all LEDs off */
|
||||
// p_leds <: 0x0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,316 @@
|
||||
#include "biquad_standalone.h"
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
|
||||
// 常量定义
|
||||
#define Q_factor 30
|
||||
#define BOOST_BSHIFT 2
|
||||
|
||||
// 如果没有定义M_PI,则手动定义
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
static const float pi = (float)M_PI;
|
||||
static const float log_2 = 0.69314718055f;
|
||||
static const float db_2 = 6.02059991328f; // 20*log10(2)
|
||||
|
||||
// 辅助函数实现
|
||||
static inline int32_t _float2fixed(float x, int32_t q) {
|
||||
if (x < 0.0f) return (((float)(1u << q)) * x - 0.5f);
|
||||
if (x > 0.0f) return (((float)((1u << q) - 1)) * x + 0.5f);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int32_t _float2fixed_assert(float x, int32_t q) {
|
||||
float max_val = (float)(1 << (31 - q));
|
||||
// 简单的断言检查,如果超出范围则返回边界值
|
||||
if (x > max_val) x = max_val;
|
||||
if (x < -max_val) x = -max_val;
|
||||
return _float2fixed(x, q);
|
||||
}
|
||||
|
||||
// 简单的三角函数实现,使用标准库 - 重命名以避免冲突
|
||||
static inline float biquad_sin(float x) {
|
||||
return sinf(x);
|
||||
}
|
||||
|
||||
static inline float biquad_cos(float x) {
|
||||
return cosf(x);
|
||||
}
|
||||
|
||||
static inline float _check_fc(float fc, float fs) {
|
||||
float fc_sat = fc;
|
||||
// saturate if > fs/2
|
||||
if (fc_sat >= fs / 2.0f) {
|
||||
fc_sat = fs / 2.0f;
|
||||
}
|
||||
return fc_sat;
|
||||
}
|
||||
|
||||
static inline float _check_gain(float gain, float max_gain) {
|
||||
float gain_sat = gain;
|
||||
// saturate if > max_gain
|
||||
if (gain_sat >= max_gain) {
|
||||
gain_sat = max_gain;
|
||||
}
|
||||
return gain_sat;
|
||||
}
|
||||
|
||||
void eq_biquad_bypass(q2_30 coeffs[5]) {
|
||||
coeffs[0] = 1 << Q_factor;
|
||||
coeffs[1] = 0;
|
||||
coeffs[2] = 0;
|
||||
coeffs[3] = 0;
|
||||
coeffs[4] = 0;
|
||||
}
|
||||
|
||||
void eq_biquad_mute(q2_30 coeffs[5]) {
|
||||
coeffs[0] = 0;
|
||||
coeffs[1] = 0;
|
||||
coeffs[2] = 0;
|
||||
coeffs[3] = 0;
|
||||
coeffs[4] = 0;
|
||||
}
|
||||
|
||||
left_shift_t eq_biquad_gain(q2_30 coeffs[5], const float gain_db) {
|
||||
float A = powf(10.0f, (gain_db * (1.0f / 20.0f)));
|
||||
|
||||
coeffs[0] = _float2fixed_assert(A, Q_factor - BOOST_BSHIFT);
|
||||
coeffs[1] = 0;
|
||||
coeffs[2] = 0;
|
||||
coeffs[3] = 0;
|
||||
coeffs[4] = 0;
|
||||
|
||||
return BOOST_BSHIFT;
|
||||
}
|
||||
|
||||
void eq_biquad_lowpass(q2_30 coeffs[5], const float fc, const float fs, const float filter_Q) {
|
||||
float fc_sat = _check_fc(fc, fs);
|
||||
|
||||
// Compute common factors
|
||||
float K = tanf(pi * fc_sat / fs);
|
||||
float KK = K * K;
|
||||
float KQ = K / filter_Q;
|
||||
float norm = 1.0f / (1.0f + KQ + KK);
|
||||
|
||||
// Compute coeffs
|
||||
float b0 = KK * norm;
|
||||
float b1 = 2.0f * b0;
|
||||
float b2 = b0;
|
||||
float a1 = 2.0f * (KK - 1.0f) * norm;
|
||||
float a2 = (1.0f - KQ + KK) * norm;
|
||||
|
||||
//DPRINTF("b0: %f \n b1: %f \n b2: %f \n a1: %f \n a2: %f\n", b0, b1, b2, a1, a2);
|
||||
// Store as fixed-point values
|
||||
coeffs[0] = _float2fixed_assert(b0, Q_factor);
|
||||
coeffs[1] = _float2fixed_assert(b1, Q_factor);
|
||||
coeffs[2] = _float2fixed_assert(b2, Q_factor);
|
||||
coeffs[3] = _float2fixed_assert(-a1, Q_factor);
|
||||
coeffs[4] = _float2fixed_assert(-a2, Q_factor);
|
||||
}
|
||||
|
||||
void eq_biquad_highpass(q2_30 coeffs[5], const float fc, const float fs, const float filter_Q) {
|
||||
float fc_sat = _check_fc(fc, fs);
|
||||
|
||||
// Compute common factors
|
||||
float K = tanf(pi * fc_sat / fs);
|
||||
float KK = K * K;
|
||||
float KQ = K / filter_Q;
|
||||
float norm = 1.0f / (1.0f + KQ + KK);
|
||||
|
||||
// Compute coeffs
|
||||
float b0 = norm;
|
||||
float b1 = -2.0f * b0;
|
||||
float b2 = b0;
|
||||
float a1 = 2.0f * (KK - 1.0f) * norm;
|
||||
float a2 = (1.0f - KQ + KK) * norm;
|
||||
|
||||
// Store as fixed-point values
|
||||
coeffs[0] = _float2fixed_assert(b0, Q_factor);
|
||||
coeffs[1] = _float2fixed_assert(b1, Q_factor);
|
||||
coeffs[2] = _float2fixed_assert(b2, Q_factor);
|
||||
coeffs[3] = _float2fixed_assert(-a1, Q_factor);
|
||||
coeffs[4] = _float2fixed_assert(-a2, Q_factor);
|
||||
}
|
||||
|
||||
void eq_biquad_allpass(q2_30 coeffs[5], const float fc, const float fs, const float filter_Q) {
|
||||
float fc_sat = _check_fc(fc, fs);
|
||||
|
||||
float K = tanf(pi * fc_sat / fs);
|
||||
float norm = 1.0f / (1.0f + K / filter_Q + K * K);
|
||||
|
||||
float b0 = (1.0f - K / filter_Q + K * K) * norm;
|
||||
float b1 = 2.0f * (K * K - 1.0f) * norm;
|
||||
float b2 = 1.0f;
|
||||
float a1 = b1;
|
||||
float a2 = b0;
|
||||
|
||||
coeffs[0] = _float2fixed_assert(b0, Q_factor);
|
||||
coeffs[1] = _float2fixed_assert(b1, Q_factor);
|
||||
coeffs[2] = _float2fixed_assert(b2, Q_factor);
|
||||
coeffs[3] = _float2fixed_assert(-a1, Q_factor);
|
||||
coeffs[4] = _float2fixed_assert(-a2, Q_factor);
|
||||
}
|
||||
|
||||
// 动态计算bshift的函数
|
||||
static left_shift_t calculate_bshift(float b0, float b1, float b2) {
|
||||
float max_b = fabsf(b0);
|
||||
if (fabsf(b1) > max_b) max_b = fabsf(b1);
|
||||
if (fabsf(b2) > max_b) max_b = fabsf(b2);
|
||||
if (max_b == 0.0f) return 0;
|
||||
int bshift = 0;
|
||||
if (max_b >= 1.0f) {
|
||||
float temp = max_b;
|
||||
while (temp >= 2.0f) { temp /= 2.0f; bshift++; }
|
||||
} else {
|
||||
float temp = max_b;
|
||||
while (temp < 1.0f) { temp *= 2.0f; bshift--; }
|
||||
bshift--;
|
||||
}
|
||||
return (bshift >= 0) ? bshift : 0;
|
||||
}
|
||||
|
||||
left_shift_t eq_biquad_peaking(q2_30 coeffs[5], const float fc, const float fs, const float filter_Q, const float gain_db) {
|
||||
float gain_db_sat = _check_gain(gain_db, 20.0f * db_2);
|
||||
float fc_sat = _check_fc(fc, fs);
|
||||
float V = powf(10.0f, fabsf(gain_db_sat) / 20.0f);
|
||||
float K = tanf(pi * fc_sat / fs);
|
||||
float norm, b0, b1, b2, a1, a2;
|
||||
|
||||
if (gain_db_sat >= 0) {
|
||||
norm = 1.0f / (1.0f + 1.0f/filter_Q * K + K * K);
|
||||
b0 = (1.0f + V/filter_Q * K + K * K) * norm;
|
||||
b1 = 2.0f * (K * K - 1.0f) * norm;
|
||||
b2 = (1.0f - V/filter_Q * K + K * K) * norm;
|
||||
a1 = b1;
|
||||
a2 = (1.0f - 1.0f/filter_Q * K + K * K) * norm;
|
||||
} else {
|
||||
norm = 1.0f / (1.0f + V/filter_Q * K + K * K);
|
||||
b0 = (1.0f + 1.0f/filter_Q * K + K * K) * norm;
|
||||
b1 = 2.0f * (K * K - 1.0f) * norm;
|
||||
b2 = (1.0f - 1.0f/filter_Q * K + K * K) * norm;
|
||||
a1 = b1;
|
||||
a2 = (1.0f - V/filter_Q * K + K * K) * norm;
|
||||
}
|
||||
|
||||
left_shift_t bshift = calculate_bshift(b0, b1, b2);
|
||||
coeffs[0] = _float2fixed_assert(b0, Q_factor - bshift);
|
||||
coeffs[1] = _float2fixed_assert(b1, Q_factor - bshift);
|
||||
coeffs[2] = _float2fixed_assert(b2, Q_factor - bshift);
|
||||
coeffs[3] = _float2fixed_assert(-a1, Q_factor);
|
||||
coeffs[4] = _float2fixed_assert(-a2, Q_factor);
|
||||
return bshift;
|
||||
}
|
||||
|
||||
left_shift_t eq_biquad_lowshelf(q2_30 coeffs[5], const float fc, const float fs, const float filter_Q, const float gain_db) {
|
||||
float gain_db_sat = _check_gain(gain_db, 20.0f * db_2);
|
||||
float fc_sat = _check_fc(fc, fs);
|
||||
|
||||
// 使用与Python端BiquadFilterCalculator.calculate("lowshelf")完全一致的算法
|
||||
float V = powf(10.0f, fabsf(gain_db_sat) / 20.0f); // 与Python端一致
|
||||
float K = tanf(pi * fc_sat / fs); // 与Python端一致:K = tan(π * Fc / Fs)
|
||||
float norm = 0.0f;
|
||||
|
||||
// 根据增益正负选择不同的计算方式,与Python端完全一致
|
||||
if (gain_db_sat >= 0) {
|
||||
norm = 1.0f / (1.0f + sqrtf(2.0f) * K + K * K);
|
||||
float b0 = (1.0f + sqrtf(2.0f * V) * K + V * K * K) * norm;
|
||||
float b1 = 2.0f * (V * K * K - 1.0f) * norm;
|
||||
float b2 = (1.0f - sqrtf(2.0f * V) * K + V * K * K) * norm;
|
||||
float a1 = 2.0f * (K * K - 1.0f) * norm;
|
||||
float a2 = (1.0f - sqrtf(2.0f) * K + K * K) * norm;
|
||||
|
||||
// DPRINTF("b0: %f \n b1: %f \n b2: %f \n a1: %f \n a2: %f\n", b0, b1, b2, a1, a2);
|
||||
|
||||
// 动态计算bshift
|
||||
left_shift_t bshift = calculate_bshift(b0, b1, b2);
|
||||
|
||||
// Store as fixed-point values
|
||||
coeffs[0] = _float2fixed_assert(b0, Q_factor - bshift);
|
||||
coeffs[1] = _float2fixed_assert(b1, Q_factor - bshift);
|
||||
coeffs[2] = _float2fixed_assert(b2, Q_factor - bshift);
|
||||
coeffs[3] = _float2fixed_assert(-a1, Q_factor);
|
||||
coeffs[4] = _float2fixed_assert(-a2, Q_factor);
|
||||
|
||||
return bshift;
|
||||
} else {
|
||||
norm = 1.0f / (1.0f + sqrtf(2.0f * V) * K + V * K * K);
|
||||
float b0 = (1.0f + sqrtf(2.0f) * K + K * K) * norm;
|
||||
float b1 = 2.0f * (K * K - 1.0f) * norm;
|
||||
float b2 = (1.0f - sqrtf(2.0f) * K + K * K) * norm;
|
||||
float a1 = 2.0f * (V * K * K - 1.0f) * norm;
|
||||
float a2 = (1.0f - sqrtf(2.0f * V) * K + V * K * K) * norm;
|
||||
|
||||
// DPRINTF("b0: %f \n b1: %f \n b2: %f \n a1: %f \n a2: %f\n", b0, b1, b2, a1, a2);
|
||||
|
||||
// 动态计算bshift
|
||||
left_shift_t bshift = calculate_bshift(b0, b1, b2);
|
||||
|
||||
// Store as fixed-point values
|
||||
coeffs[0] = _float2fixed_assert(b0, Q_factor - bshift);
|
||||
coeffs[1] = _float2fixed_assert(b1, Q_factor - bshift);
|
||||
coeffs[2] = _float2fixed_assert(b2, Q_factor - bshift);
|
||||
coeffs[3] = _float2fixed_assert(-a1, Q_factor);
|
||||
coeffs[4] = _float2fixed_assert(-a2, Q_factor);
|
||||
|
||||
return bshift;
|
||||
}
|
||||
}
|
||||
|
||||
left_shift_t eq_biquad_highshelf(q2_30 coeffs[5], const float fc, const float fs, const float filter_Q, const float gain_db) {
|
||||
float gain_db_sat = _check_gain(gain_db, 20.0f * db_2);
|
||||
float fc_sat = _check_fc(fc, fs);
|
||||
|
||||
// 使用与Python端BiquadFilterCalculator.calculate("highshelf")完全一致的算法
|
||||
float V = powf(10.0f, fabsf(gain_db_sat) / 20.0f); // 与Python端一致
|
||||
float K = tanf(pi * fc_sat / fs); // 与Python端一致:K = tan(π * Fc / Fs)
|
||||
float norm = 0.0f;
|
||||
|
||||
// 根据增益正负选择不同的计算方式,与Python端完全一致
|
||||
if (gain_db_sat >= 0) {
|
||||
norm = 1.0f / (1.0f + sqrtf(2.0f) * K + K * K);
|
||||
float b0 = (V + sqrtf(2.0f * V) * K + K * K) * norm;
|
||||
float b1 = 2.0f * (K * K - V) * norm;
|
||||
float b2 = (V - sqrtf(2.0f * V) * K + K * K) * norm;
|
||||
float a1 = 2.0f * (K * K - 1.0f) * norm;
|
||||
float a2 = (1.0f - sqrtf(2.0f) * K + K * K) * norm;
|
||||
|
||||
// DPRINTF("b0: %f \n b1: %f \n b2: %f \n a1: %f \n a2: %f\n", b0, b1, b2, a1, a2);
|
||||
|
||||
// 动态计算bshift
|
||||
left_shift_t bshift = calculate_bshift(b0, b1, b2);
|
||||
|
||||
// Store as fixed-point values
|
||||
coeffs[0] = _float2fixed_assert(b0, Q_factor - bshift);
|
||||
coeffs[1] = _float2fixed_assert(b1, Q_factor - bshift);
|
||||
coeffs[2] = _float2fixed_assert(b2, Q_factor - bshift);
|
||||
coeffs[3] = _float2fixed_assert(-a1, Q_factor);
|
||||
coeffs[4] = _float2fixed_assert(-a2, Q_factor);
|
||||
|
||||
return bshift;
|
||||
} else {
|
||||
norm = 1.0f / (V + sqrtf(2.0f * V) * K + K * K);
|
||||
float b0 = (1.0f + sqrtf(2.0f) * K + K * K) * norm;
|
||||
float b1 = 2.0f * (K * K - 1.0f) * norm;
|
||||
float b2 = (1.0f - sqrtf(2.0f) * K + K * K) * norm;
|
||||
float a1 = 2.0f * (K * K - V) * norm;
|
||||
float a2 = (V - sqrtf(2.0f * V) * K + K * K) * norm;
|
||||
|
||||
// DPRINTF("b0: %f \n b1: %f \n b2: %f \n a1: %f \n a2: %f\n", b0, b1, b2, a1, a2);
|
||||
|
||||
// 动态计算bshift
|
||||
left_shift_t bshift = calculate_bshift(b0, b1, b2);
|
||||
|
||||
// Store as fixed-point values
|
||||
coeffs[0] = _float2fixed_assert(b0, Q_factor - bshift);
|
||||
coeffs[1] = _float2fixed_assert(b1, Q_factor - bshift);
|
||||
coeffs[2] = _float2fixed_assert(b2, Q_factor - bshift);
|
||||
coeffs[3] = _float2fixed_assert(-a1, Q_factor);
|
||||
coeffs[4] = _float2fixed_assert(-a2, Q_factor);
|
||||
|
||||
return bshift;
|
||||
}
|
||||
}
|
||||
|
||||
/* Removed unused filters: bandpass, bandstop, notch, const_q, linkwitz */
|
||||
@@ -0,0 +1,26 @@
|
||||
#ifndef BIQUAD_STANDALONE_H
|
||||
#define BIQUAD_STANDALONE_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "xmath/types.h" // 包含 lib_xcore_math 的类型定义
|
||||
|
||||
// 注意:q2_30, left_shift_t, right_shift_t 已在 lib_xcore_math 中定义,不需要重复定义
|
||||
|
||||
// 函数声明
|
||||
void eq_biquad_bypass(q2_30 coeffs[5]);
|
||||
void eq_biquad_mute(q2_30 coeffs[5]);
|
||||
left_shift_t eq_biquad_gain(q2_30 coeffs[5], const float gain_db);
|
||||
void eq_biquad_lowpass(q2_30 coeffs[5], const float fc, const float fs, const float filter_Q);
|
||||
void eq_biquad_highpass(q2_30 coeffs[5], const float fc, const float fs, const float filter_Q);
|
||||
void eq_biquad_allpass(q2_30 coeffs[5], const float fc, const float fs, const float filter_Q);
|
||||
left_shift_t eq_biquad_peaking(q2_30 coeffs[5], const float fc, const float fs, const float filter_Q, const float gain_db);
|
||||
left_shift_t eq_biquad_lowshelf(q2_30 coeffs[5], const float fc, const float fs, const float filter_Q, const float gain_db);
|
||||
left_shift_t eq_biquad_highshelf(q2_30 coeffs[5], const float fc, const float fs, const float filter_Q, const float gain_db);
|
||||
|
||||
// 辅助函数声明 - 重命名以避免与系统库冲突
|
||||
static inline int32_t _float2fixed(float x, int32_t q);
|
||||
static inline int32_t _float2fixed_assert(float x, int32_t q);
|
||||
static inline float biquad_sin(float x); // 重命名为 biquad_sin
|
||||
static inline float biquad_cos(float x); // 重命名为 biquad_cos
|
||||
|
||||
#endif // BIQUAD_STANDALONE_H
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2024 XMOS LIMITED.
|
||||
#define DEBUG_PRINT_ENABLE 0
|
||||
#include "debug_print.h"
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#include <print.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <platform.h>
|
||||
#include <xs1.h>
|
||||
#include <xcore/chanend.h>
|
||||
#include <xcore/channel.h>
|
||||
#include "xc_ptr.h"
|
||||
|
||||
#include "xua_conf.h"
|
||||
|
||||
#include "share_buffer.h"
|
||||
|
||||
void dnr_exchange_buffer(int32_t *data);
|
||||
void buffer_exchange(chanend_t c_data, unsigned sampsFromUsbToAudio[], unsigned sampsFromAudioToUsb[]) {
|
||||
chan_out_buf_word (c_data, sampsFromUsbToAudio, 2);
|
||||
chan_out_buf_word (c_data, sampsFromAudioToUsb, 2);
|
||||
chan_in_buf_word (c_data , sampsFromUsbToAudio, 2);
|
||||
chan_in_buf_word (c_data , sampsFromAudioToUsb, 2);
|
||||
}
|
||||
|
||||
|
||||
void dsp_main (chanend_t c_data) {
|
||||
int play_input[NUM_USB_CHAN_OUT];
|
||||
int play_output[I2S_CHANS_DAC];
|
||||
int mic_input[NUM_USB_CHAN_IN];
|
||||
int mic_output[I2S_CHANS_ADC];
|
||||
int count = 0;
|
||||
unsigned ch[1] = {2};
|
||||
while (1) {
|
||||
chan_in_buf_word (c_data , play_input, 2) ;
|
||||
chan_in_buf_word (c_data , mic_input, 2) ;
|
||||
chan_out_buf_word (c_data , play_output, I2S_CHANS_DAC);
|
||||
chan_out_buf_word (c_data , mic_output, I2S_CHANS_ADC);
|
||||
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);
|
||||
dnr_exchange_buffer(mic_input);
|
||||
mic_output[0] = mic_input[0];
|
||||
mic_output[1] = mic_input[1];
|
||||
// dnr_exchange_buffer((int32_t *)mic_input, (int32_t *)mic_output);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#ifndef _C_DSP_H_
|
||||
#define _C_DSP_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// #define AUDIO_T_16
|
||||
|
||||
#if defined(AUDIO_T_16)
|
||||
typedef int16_t AUDIO_T;
|
||||
#else // defined(AUDIO_T_32)
|
||||
typedef int32_t AUDIO_T;
|
||||
#endif
|
||||
|
||||
#define FRAME_SIZE 8 //128 samples / 48kHz = 2.6ms
|
||||
|
||||
void hid_update(unsigned char hid_data);
|
||||
|
||||
// mic level
|
||||
#define MIN_MIC_LEVEL 0
|
||||
#define MAX_MIC_LEVEL 9
|
||||
#define DEFAULT_MIC_LEVEL 5
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
// Copyright 2020-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#ifndef AIC3204_H_
|
||||
#define AIC3204_H_
|
||||
|
||||
// TLV320AIC3204 Device I2C Address
|
||||
#define AIC3204_I2C_DEVICE_ADDR 0x18
|
||||
|
||||
#define CODEC_I2C_DEVICE_ADDR AIC3204_I2C_DEVICE_ADDR
|
||||
|
||||
// TLV320AIC3204 Register Addresses
|
||||
// Page 0
|
||||
#define AIC3204_PAGE_CTRL 0x00 // Register 0 - Page Control
|
||||
#define AIC3204_SW_RST 0x01 // Register 1 - Software Reset
|
||||
#define AIC3204_NDAC 0x0B // Register 11 - NDAC Divider Value
|
||||
#define AIC3204_MDAC 0x0C // Register 12 - MDAC Divider Value
|
||||
#define AIC3204_DOSR_MSB 0x0d // Register 14 - DOSR Divider Value (MS Byte)
|
||||
#define AIC3204_DOSR_LSB 0x0e // Register 14 - DOSR Divider Value (LS Byte)
|
||||
#define AIC3204_NADC 0x12 // Register 18 - NADC Divider Value
|
||||
#define AIC3204_MADC 0x13 // Register 19 - MADC Divider Value
|
||||
#define AIC3204_AOSR 0x14 // Register 20 - AOSR Divider Value
|
||||
#define AIC3204_CLK_MUL 0x19 // Register 25
|
||||
#define AIC3204_CLK_DIV 0x1A // Register 26
|
||||
#define AIC3204_CODEC_IF 0x1B // Register 27 - CODEC Interface Control
|
||||
#define AIC3204_D_OFFSET 0x1C // Register 28 -
|
||||
#define AIC3204_LOOPBACK 0x1D // Register 29 -
|
||||
#define AIC3204_BCLK_DIV 0x1E // Register 30 - --------
|
||||
#define AIC3204_CLK_MUL 0x1F // Register 31 -
|
||||
#define AIC3204_BCLK_SEL 0x20 // Register 32 - 0:Primary; 1:Second
|
||||
#define AIC3204_DAC_SIG_PROC 0x3C // Register 60 - DAC Sig Processing Block Control
|
||||
#define AIC3204_ADC_SIG_PROC 0x3D // Register 61 - ADC Sig Processing Block Control
|
||||
#define AIC3204_DAC_CH_SET1 0x3F // Register 63 - DAC Channel Setup 1
|
||||
#define AIC3204_DAC_CH_SET2 0x40 // Register 64 - DAC Channel Setup 2
|
||||
#define AIC3204_DACL_VOL_D 0x41 // Register 65 - DAC Left Digital Vol Control
|
||||
#define AIC3204_DACR_VOL_D 0x42 // Register 66 - DAC Right Digital Vol Control
|
||||
#define AIC3204_HEADSET_DET 0x43 // Register 67 - Headset Detection configuration
|
||||
#define AIC3204_DRC_CON1 0x44 // Register 68 - DRC control reg1
|
||||
#define AIC3204_DRC_CON2 0x45 // Register 69 - DRC control reg2
|
||||
#define AIC3204_DRC_CON3 0x46 // Register 70 - DRC control reg3
|
||||
#define AIC3204_ADC_CH_SET 0x51 // Register 81 - ADC Channel Setup
|
||||
#define AIC3204_ADC_FGA_MUTE 0x52 // Register 82 - ADC Fine Gain Adjust/Mute
|
||||
#define AIC3204_ADC_CH1_SET 0x53 // Register 83 - ADC L_CH vol
|
||||
#define AIC3204_ADC_CH2_SET 0x54 // Register 84 - ADC R_CH vol
|
||||
#define AIC3204_ADC_PHA_SET 0x55 // Register 84 - ADC Phase Adjust Reg
|
||||
//0x56~0x5c: L-CH agc control regs
|
||||
//0x5e~0x65: R-CH agc control regs
|
||||
///0x66~0x67: DC measurement regs
|
||||
//0x68~0x6d: DC Measurement output regs
|
||||
|
||||
// Page 1
|
||||
#define AIC3204_PAGE_SEL1 0x00 // Register 0 - Page Select Reg
|
||||
#define AIC3204_PWR_CFG 0x01 // Register 1 - Power Config
|
||||
#define AIC3204_LDO_CTRL 0x02 // Register 2 - LDO Control
|
||||
#define AIC3204_PLAY_CFG1 0x03 // Register 3 - Playback Config 1
|
||||
#define AIC3204_PLAY_CFG2 0x04 // Register 4 - Playback Config 2
|
||||
#define AIC3204_OP_PWR_CTRL 0x09 // Register 9 - Output Driver Power Control
|
||||
#define AIC3204_CM_CTRL 0x0A // Register 10 - Common Mode Control
|
||||
#define AIC3204_HPL_ROUTE 0x0C // Register 12 - HPL Routing Select
|
||||
#define AIC3204_HPR_ROUTE 0x0D // Register 13 - HPR Routing Select
|
||||
#define AIC3204_HPL_GAIN 0x10 // Register 16 - HPL Driver Gain
|
||||
#define AIC3204_HPR_GAIN 0x11 // Register 17 - HPR Driver Gain
|
||||
#define AIC3204_HP_START 0x14 // Register 20 - Headphone Driver Startup
|
||||
#define AIC3204_LPGA_P_ROUTE 0x34 // Register 52 - Left PGA Positive Input Route
|
||||
#define AIC3204_LPGA_N_ROUTE 0x36 // Register 54 - Left PGA Negative Input Route
|
||||
#define AIC3204_RPGA_P_ROUTE 0x37 // Register 55 - Right PGA Positive Input Route
|
||||
#define AIC3204_RPGA_N_ROUTE 0x39 // Register 57 - Right PGA Negative Input Route
|
||||
#define AIC3204_LPGA_VOL 0x3B // Register 59 - Left PGA Volume
|
||||
#define AIC3204_RPGA_VOL 0x3C // Register 60 - Right PGA Volume
|
||||
#define AIC3204_ADC_PTM 0x3D // Register 61 - ADC Power Tune Config
|
||||
#define AIC3204_ADC_VOL 0x3E // Register 62 - ADC Analog Gain Control Flag
|
||||
#define AIC3204_AN_IN_CHRG 0x47 // Register 71 - Analog Input Quick Charging Config
|
||||
#define AIC3204_REF_STARTUP 0x7B // Register 123 - Reference Power Up Config
|
||||
|
||||
int aic3204_init(void);
|
||||
|
||||
#endif /* AIC3204_H_ */
|
||||
@@ -0,0 +1,55 @@
|
||||
#ifndef AZP_H_
|
||||
#define AZP_H_
|
||||
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
typedef enum
|
||||
{
|
||||
errAZP_NoError = 0, // No error
|
||||
errAZP_NotReady, // Not ready
|
||||
errAZP_InvalidParam, // Invalid parameter
|
||||
errAZP_InvalidLicense, // Invalid license
|
||||
errAZP_BufferOverflow, // Buffer overflow
|
||||
errAZP_BufferTooSmall, // Buffer too small
|
||||
} AZP_STATUS;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int8_t *buffer1; // Pointer to the first buffer
|
||||
int8_t *buffer2; // Pointer to the second buffer
|
||||
int32_t buffer1_size; // Size of the first buffer
|
||||
int32_t buffer2_size; // Size of the second buffer
|
||||
int32_t sample_rate; // Sample rate, only support 16000Hz
|
||||
} azp_dnr_param_t;
|
||||
|
||||
/// @brief DNR initialization
|
||||
/// @param param Configuration parameters
|
||||
/// @return License status
|
||||
/// @brief DNR initialization
|
||||
/// @param param Configuration parameters
|
||||
/// @return License status
|
||||
AZP_STATUS AI_DNR_init(azp_dnr_param_t *param);
|
||||
|
||||
/// @brief DNR processing
|
||||
/// @param audio Q31 input and output
|
||||
/// @return License status
|
||||
AZP_STATUS AI_DNR_Processing(int32_t *audio);
|
||||
|
||||
/// @brief Get version number
|
||||
/// @return If not licensed, returns NULL
|
||||
char *AI_DNR_Version();
|
||||
|
||||
/// @brief Get the size of the working buffers
|
||||
/// @param buf_size Size of the first buffer
|
||||
/// @param buf_size2 Size of the second buffer
|
||||
void getBufferSize(int32_t *buf_size, int32_t *buf_size2);
|
||||
|
||||
/// @brief Set the noise reduction depth
|
||||
/// @param dB Range (-200 to 0 dB)
|
||||
/// -200: Maximum noise reduction
|
||||
/// 0: No noise reduction
|
||||
void setNoisy_mix_factor(float dB);
|
||||
|
||||
|
||||
#endif // AZP_H_
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2016-2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#if UART_DEBUG || DEBUG_MEMORY_LOG_ENABLED
|
||||
#define DEBUG_PRINT_ENABLE 1
|
||||
#endif
|
||||
|
||||
#include <xs1.h>
|
||||
#include <xua_conf.h>
|
||||
#include "ringbuf.h"
|
||||
#include <xcore/chanend.h>
|
||||
#include <xcore/channel.h>
|
||||
#include "dnr_dsp_buf.h"
|
||||
#include "xc_ptr.h"
|
||||
#include "debug_print.h"
|
||||
|
||||
unsigned g_dsp_eof = 0;
|
||||
void dnr_exchange_buffer(int32_t *data) {
|
||||
static unsigned buff_index = 0;
|
||||
write_to_sample_in_buf(data[1], buff_index, 0);
|
||||
read_from_sample_out_buf(&data[1],buff_index, 0);
|
||||
data[0] = data[1];
|
||||
|
||||
buff_index++;
|
||||
#if DNR_11MS
|
||||
if (buff_index == 128)
|
||||
{
|
||||
#else
|
||||
if (buff_index == 512)
|
||||
{
|
||||
#endif
|
||||
buf_slot_rotate();
|
||||
buff_index = 0;
|
||||
SET_SHARED_GLOBAL(g_dsp_eof, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Aizip_DNR_init(void);
|
||||
|
||||
void dnr_dsp_proc_task(void)
|
||||
{
|
||||
Aizip_DNR_init();
|
||||
while(1) {
|
||||
unsigned dsp_eof = 0;
|
||||
GET_SHARED_GLOBAL(dsp_eof, g_dsp_eof);
|
||||
if (dsp_eof) {
|
||||
SET_SHARED_GLOBAL(g_dsp_eof, 0);
|
||||
start_dsp_processing();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
//
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
|
||||
#if UART_DEBUG || DEBUG_MEMORY_LOG_ENABLED
|
||||
#define DEBUG_PRINT_ENABLE 1
|
||||
#endif
|
||||
|
||||
#include <xs1.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <platform.h>
|
||||
#include <string.h>
|
||||
#include "dnr_dsp_buf.h"
|
||||
#include "aizip_dnr.h"
|
||||
#include "debug_print.h"
|
||||
#include "flash.h"
|
||||
|
||||
//for AGC
|
||||
//static agc_stage_ctx_t DWORD_ALIGNED agc_stage_state = {};
|
||||
|
||||
static unsigned __attribute__((aligned (4))) dsp_dnr_frame_buf[BUF_SLOT_NUM][DSP_CH_NUM][DNR_DSP_FRAME_SIZE];
|
||||
|
||||
unsigned sample_in_buf_slot=0;
|
||||
unsigned processing_buf_slot=2;
|
||||
unsigned sample_out_buf_slot=1;
|
||||
|
||||
|
||||
void dsp_buf_init()
|
||||
{
|
||||
sample_in_buf_slot=0;
|
||||
sample_out_buf_slot=1;
|
||||
processing_buf_slot=2;
|
||||
}
|
||||
|
||||
static void buf_slot_inc(unsigned* buf_slot_input)
|
||||
{
|
||||
if(*buf_slot_input == BUF_SLOT_NUM-1){
|
||||
*buf_slot_input = 0;
|
||||
}
|
||||
else{
|
||||
*buf_slot_input = *buf_slot_input+1;
|
||||
}
|
||||
}
|
||||
|
||||
void buf_slot_rotate()
|
||||
{
|
||||
buf_slot_inc(&sample_in_buf_slot);
|
||||
buf_slot_inc(&sample_out_buf_slot);
|
||||
buf_slot_inc(&processing_buf_slot);
|
||||
}
|
||||
|
||||
void write_to_sample_in_buf(unsigned data, unsigned index, unsigned ch)
|
||||
{
|
||||
dsp_dnr_frame_buf[sample_in_buf_slot][ch][index]=data;
|
||||
}
|
||||
|
||||
void read_from_sample_out_buf(unsigned* read_data, unsigned index, unsigned ch)
|
||||
{
|
||||
*read_data = dsp_dnr_frame_buf[sample_out_buf_slot][ch][index];
|
||||
}
|
||||
#if DNR_11MS
|
||||
int8_t buffer[4208] __attribute__((aligned(4)));
|
||||
int8_t buffer2[31136] __attribute__((aligned(4)));
|
||||
#else
|
||||
int8_t buffer[21416] __attribute__((aligned(4)));
|
||||
int8_t buffer2[31712] __attribute__((aligned(4)));
|
||||
#endif
|
||||
azp_dnr_param_t pram = {
|
||||
.buffer1 = buffer,
|
||||
.buffer1_size = sizeof(buffer),
|
||||
.buffer2 = buffer2,
|
||||
.buffer2_size = sizeof(buffer2),
|
||||
.sample_rate = 48000};
|
||||
|
||||
unsigned g_dnr_init_flag = 0;
|
||||
void Aizip_DNR_init(void)
|
||||
{
|
||||
delay_microseconds(10000);
|
||||
// setFlashPortPins(XS1_PORT_1B,XS1_PORT_1C,XS1_PORT_4B, XS1_CLKBLK_3);
|
||||
|
||||
int sta = AI_DNR_init(&pram);
|
||||
g_dnr_init_flag = 1;
|
||||
debug_printf("AI_DNR_init status %d\n", sta);
|
||||
}
|
||||
|
||||
void start_dsp_processing(void)
|
||||
{
|
||||
float level = -200;
|
||||
|
||||
setNoisy_mix_factor(level);
|
||||
|
||||
AI_DNR_Processing((int32_t *)&dsp_dnr_frame_buf[processing_buf_slot][0][0]);
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef __DNR_DSP_BUF_H__
|
||||
#define __DNR_DSP_BUF_H__
|
||||
|
||||
#include <xs1.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <platform.h>
|
||||
#include <xcore/chanend.h>
|
||||
#include <xcore/channel.h>
|
||||
#if DNR_11MS
|
||||
#define DNR_DSP_FRAME_SIZE 128
|
||||
#else
|
||||
#define DNR_DSP_FRAME_SIZE 512
|
||||
#endif
|
||||
#define BUF_SLOT_NUM 3 //one for input, one for output, one for processing
|
||||
#define DSP_CH_NUM 2
|
||||
|
||||
#if __XC__
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void dnr_set_chan(chanend_t dnr_tile0_c, chanend_t dnr_tile1_c);
|
||||
|
||||
void dsp_buf_init();
|
||||
void buf_slot_rotate();
|
||||
void write_to_sample_in_buf(unsigned data, unsigned index, unsigned ch);
|
||||
void read_from_sample_out_buf(unsigned* read_data, unsigned index, unsigned ch);
|
||||
|
||||
void start_dsp_processing(void);
|
||||
void Aizip_DNR_init(void);
|
||||
|
||||
#if __XC__
|
||||
} //extern c
|
||||
#endif
|
||||
#endif //RINGBUFFER_H
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
#ifndef __FLASH_H__
|
||||
#define __FLASH_H__
|
||||
#include "stdint.h"
|
||||
void setFlashPortPins(uint32_t cs,uint32_t sclk,uint32_t sio,uint32_t clkblk);
|
||||
#endif
|
||||
@@ -0,0 +1,45 @@
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef __RINGBUF_H__
|
||||
#define __RINGBUF_H__
|
||||
|
||||
#include <xs1.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <platform.h>
|
||||
|
||||
#if __XC__
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define FRAME_SIZE 120 //101623 - from 256 to 120
|
||||
|
||||
#define RF_CHAN_NUM 2 //stereo. Multichannel uses NUM_USB_CHAN_OUT
|
||||
//
|
||||
#define RB_SIZE FRAME_SIZE*RF_CHAN_NUM*16 //2 channel, 32-bit, 16 frame
|
||||
#define RB_MASK (RB_SIZE - 1)
|
||||
|
||||
|
||||
extern uint32_t r_buffer[RB_SIZE];
|
||||
|
||||
typedef struct {
|
||||
uint32_t * buf_addr;
|
||||
int next_empty;
|
||||
int next_data;
|
||||
int full;
|
||||
int empty;
|
||||
} ring_buffer_t;
|
||||
|
||||
void rb_init(void);
|
||||
void rb_put_word(uint32_t data);
|
||||
uint32_t rb_get_word(void);
|
||||
int rb_is_full(void);
|
||||
int rb_is_empty(void);
|
||||
|
||||
#if __XC__
|
||||
} //extern c
|
||||
#endif
|
||||
|
||||
#endif //RINGBUFFER_H
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef __DNR_DSP_BUF_H__
|
||||
#define __DNR_DSP_BUF_H__
|
||||
|
||||
#include <xs1.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <platform.h>
|
||||
#include "c_dsp.h"
|
||||
|
||||
#define DNR_50MS 1
|
||||
//#define DEBUG_DNR
|
||||
#if (DNR_50MS == 1)
|
||||
#define DNR_DSP_FRAME_SIZE 512
|
||||
#else
|
||||
#define DNR_DSP_FRAME_SIZE 128
|
||||
#endif
|
||||
|
||||
#define BUF_SLOT_NUM 3 //one for input, one for output, one for processing
|
||||
#define DSP_CH_NUM 2
|
||||
|
||||
#if __XC__
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void dsp_buf_init();
|
||||
void buf_slot_rotate();
|
||||
void write_to_sample_in_buf(unsigned data, unsigned index, unsigned ch);
|
||||
void read_from_sample_out_buf(unsigned* read_data, unsigned index, unsigned ch);
|
||||
void start_dsp_processing(unsigned samFreq);
|
||||
|
||||
|
||||
#if __XC__
|
||||
} //extern c
|
||||
#endif
|
||||
|
||||
#define AGC_ENABLED 1
|
||||
#define DNR_ENABLED 1
|
||||
|
||||
#define KEY_MIC_VOL_DN 0x08
|
||||
#define KEY_MUTE 0x10
|
||||
#define KEY_MIC_VOL_UP 0x20
|
||||
#define KEY_PLAY_VOL_DN 0x40
|
||||
#define KEY_PLAY_VOL_UP 0x80
|
||||
#define KEY_BITS (KEY_MIC_VOL_DN | KEY_MUTE | KEY_MIC_VOL_UP | KEY_PLAY_VOL_DN | KEY_PLAY_VOL_UP)
|
||||
|
||||
#if defined (PHATEN_GSV2)
|
||||
#define DEBOUNCE_TIMEOUT 10 // in units of 2.6ms; 128 samples/frame
|
||||
#else
|
||||
#error "Please define DEBOUNCE_TIMEOUT"
|
||||
#endif
|
||||
|
||||
#define MUTED_MIC 0x5A
|
||||
#define UNMUTED_MIC 0xA5
|
||||
|
||||
// 改动原因:添加HID控制命令宏定义,用于button_task中的按键处理(从dnr_dsp_buf.c移到这里,以便dsp.c可以访问)
|
||||
#define HID_CONTROL_PLAYPAUSE 0x01
|
||||
#define HID_CONTROL_NEXT 0x02
|
||||
#define HID_CONTROL_PREV 0x04
|
||||
#define HID_CONTROL_VOLUP 0x00
|
||||
#define HID_CONTROL_VOLDN 0x01
|
||||
#define HID_CONTROL_MUTE 0x20
|
||||
|
||||
#endif //RINGBUFFER_H
|
||||
|
||||
1329
sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/dsp.c
Normal file
1329
sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/dsp.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,200 @@
|
||||
#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 g_windows_detect_done;
|
||||
|
||||
#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(100);
|
||||
unsigned windows_detect_done;
|
||||
GET_SHARED_GLOBAL(windows_detect_done, g_windows_detect_done);
|
||||
while (windows_detect_done == 0) {
|
||||
asm("nop");
|
||||
GET_SHARED_GLOBAL(windows_detect_done, g_windows_detect_done);
|
||||
}
|
||||
|
||||
#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加载失败时,使用默认模式0,EQ默认禁用
|
||||
// 改动原因:如果模式加载失败,确保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
|
||||
{
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
|
||||
|
||||
|
||||
|
||||
#define DSP_BLOCK_LENGTH (8) //DO NOT CHANGE
|
||||
|
||||
|
||||
#define DSP_TILE_0_CHANNEL_IN_COUNT (1)
|
||||
#define DSP_TILE_1_CHANNEL_IN_COUNT (1)
|
||||
|
||||
#define DSP_TILE_0_CHANNEL_OUT_COUNT (DSP_TILE_0_CHANNEL_IN_COUNT*2)
|
||||
#define DSP_TILE_1_CHANNEL_OUT_COUNT (DSP_TILE_1_CHANNEL_IN_COUNT*2)
|
||||
|
||||
#define DSP_TILE_0_WORKER_COUNT (DSP_TILE_0_CHANNEL_IN_COUNT)
|
||||
#define DSP_TILE_1_WORKER_COUNT (DSP_TILE_1_CHANNEL_IN_COUNT)
|
||||
|
||||
|
||||
#define DSP_MIXER_OUTPUT_CHANNEL_COUNT (2)
|
||||
1443
sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq.c
Normal file
1443
sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq.c
Normal file
File diff suppressed because it is too large
Load Diff
149
sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq.h
Normal file
149
sw_usb_audio/app_usb_aud_phaten_golden_6ch/src/extensions/eq.h
Normal file
@@ -0,0 +1,149 @@
|
||||
#ifndef __HEADER_EQ_HANDLER__
|
||||
#define __HEADER_EQ_HANDLER__
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "xmath/xmath.h"
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define NUM_EQ_MODES 10
|
||||
#define NUM_EQ_CHANS 2
|
||||
#define MAX_EQ_BANDS 8
|
||||
#define EQ_DISABLED_MODE 10 // 禁用EQ的模式编号
|
||||
#define EQ_PRESET_MODE_MIN 0 // 预设模式最小编号
|
||||
#define EQ_PRESET_MODE_MAX 6 // 预设模式最大编号(preset1-preset6)
|
||||
#define EQ_USER_MODE_MIN 7 // 用户模式最小编号
|
||||
#define EQ_USER_MODE_MAX 9 // 用户模式最大编号(user 1-4)
|
||||
#define EQ_MODE_MAX (NUM_EQ_MODES) // 模式最大编号(user 1-4)
|
||||
|
||||
|
||||
// Filter type definition
|
||||
typedef enum {
|
||||
FILTER_TYPE_BYPASS = 0x00,
|
||||
FILTER_TYPE_ALLPASS = 0x01,
|
||||
FILTER_TYPE_PEAKING = 0x02,
|
||||
FILTER_TYPE_LOWPASS = 0x03,
|
||||
FILTER_TYPE_HIGHPASS = 0x04,
|
||||
FILTER_TYPE_BANDPASS = 0x05,
|
||||
FILTER_TYPE_BANDSTOP = 0x06,
|
||||
FILTER_TYPE_NOTCH = 0x07,
|
||||
FILTER_TYPE_CONST_Q = 0x08,
|
||||
FILTER_TYPE_LOWSHELF = 0x09,
|
||||
FILTER_TYPE_HIGHSHELF = 0x0A
|
||||
} filter_type_t;
|
||||
|
||||
|
||||
// Filter parameter structure
|
||||
typedef struct {
|
||||
float fc; // Center frequency (Hz)
|
||||
float q; // Q value
|
||||
float bw; // Bandwidth (Hz)
|
||||
float gain; // Gain (dB)
|
||||
uint8_t index; // Filter index
|
||||
filter_type_t type; // Filter type
|
||||
uint8_t padding[2]; // 添加填充字节确保结构体对齐到4字节边界
|
||||
} filter_params_t;
|
||||
|
||||
// Filter biquad structure for runtime calculation
|
||||
typedef struct {
|
||||
int32_t coef[5][8]; // 5×8×4 = 160字节
|
||||
} filter_biquad_s32_coef_t;
|
||||
|
||||
// 注意:以下结构体定义暂时注释,因为它们可能在其他文件中定义
|
||||
// 如果需要使用,请确保包含相应的头文件
|
||||
|
||||
// 优化后的Flash存储结构 - 只存储非默认滤波器
|
||||
typedef struct {
|
||||
uint8_t active_bands_count; // 实际使用的滤波器数量
|
||||
filter_params_t active_bands[MAX_EQ_BANDS]; // 只存储非bypass的滤波器
|
||||
} eq_flash_data_t;
|
||||
|
||||
// 单个EQ参数变化记录结构(优化版)
|
||||
typedef struct {
|
||||
uint32_t sample_rate; // 采样率
|
||||
uint8_t mode; // 模式
|
||||
uint8_t channel; // 通道
|
||||
uint8_t band_index; // 滤波器索引
|
||||
filter_params_t params; // 单个滤波器参数(不包含系数)
|
||||
uint32_t timestamp; // 时间戳
|
||||
uint8_t is_dirty; // 脏标志
|
||||
} __attribute__((packed)) eq_single_param_t;
|
||||
|
||||
// 单参数存储数据库
|
||||
typedef struct {
|
||||
eq_single_param_t params[MAX_EQ_BANDS * 8 * 2]; // 最多存储8个模式×2通道的所有参数
|
||||
uint16_t param_count; // 当前参数数量
|
||||
uint16_t max_params; // 最大参数数量
|
||||
uint32_t last_save_time; // 最后保存时间
|
||||
} eq_single_param_database_t;
|
||||
|
||||
// 设备信息结构体
|
||||
typedef struct {
|
||||
char mode_names[NUM_EQ_MODES][16]; // 模式名称数组,每个16字节
|
||||
int32_t mode_gains[NUM_EQ_MODES]; // 模式增益数组,每个4字节
|
||||
} __attribute__((packed)) eq_mode_info_t;
|
||||
|
||||
// Define EQ data structure for each sample rate
|
||||
typedef struct {
|
||||
unsigned sample_rate; // Sample rate
|
||||
int32_t total_bshift;
|
||||
int32_t post_gain_db;
|
||||
filter_params_t bands[MAX_EQ_BANDS]; // Filter parameters
|
||||
filter_biquad_s32_t filter; // Filter data (运行时计算)
|
||||
} __attribute__((packed)) eq_mode_data_t;
|
||||
|
||||
|
||||
uint32_t init_eq_data(unsigned sample_freq);
|
||||
|
||||
void clear_eq_status(unsigned sample_freq, unsigned ch_no);
|
||||
|
||||
int32_t handler_eq_filter( unsigned sample_freq, uint32_t ch, int32_t new_sample);
|
||||
|
||||
void init_eq_hid_params(void);
|
||||
|
||||
// EQ参数处理函数 - 用于串口接收的EQ参数转换和存储
|
||||
int process_eq_params_from_uart(uint8_t eq_mode, uint8_t eq_index, uint32_t sample_rate, float coefficients[5]);
|
||||
|
||||
// 模式信息处理函数
|
||||
#ifdef __XC__
|
||||
// 独立的增益和名称设置/获取函数
|
||||
void set_mode_gain(uint8_t mode, int32_t gain);
|
||||
void set_mode_name(uint8_t mode, const char* unsafe name);
|
||||
void get_mode_gain(uint8_t mode, int32_t* unsafe gain);
|
||||
void get_mode_name(uint8_t mode, char* unsafe name);
|
||||
uint8_t process_uart_set_eq_mode(uint8_t mode);
|
||||
uint8_t process_uart_get_eq_mode(uint8_t * unsafe response, uint8_t response_size);
|
||||
uint8_t process_uart_set_mode_gain_and_name(uint8_t * unsafe data);
|
||||
uint8_t process_uart_set_eq_params(uint8_t * unsafe data);
|
||||
uint8_t process_uart_get_eq_params(uint8_t * unsafe data, uint8_t * unsafe response, uint8_t response_size);
|
||||
uint8_t process_uart_reset_eq_params(uint8_t * unsafe data);
|
||||
uint8_t process_uart_get_eq_mode_count(uint8_t * unsafe response, uint8_t response_size);
|
||||
uint8_t process_uart_set_and_save_eq_mode(uint8_t * unsafe data);
|
||||
|
||||
#else
|
||||
// 独立的增益和名称设置/获取函数
|
||||
void set_mode_gain(uint8_t mode, int32_t gain);
|
||||
void set_mode_name(uint8_t mode, const char* name);
|
||||
void get_mode_gain(uint8_t mode, int32_t* gain);
|
||||
void get_mode_name(uint8_t mode, char* name);
|
||||
uint8_t process_uart_set_eq_mode(uint8_t mode);
|
||||
uint8_t process_uart_get_eq_mode(uint8_t *response, uint8_t response_size);
|
||||
uint8_t process_uart_set_mode_gain_and_name(uint8_t *data);
|
||||
uint8_t process_uart_set_eq_params(uint8_t *data);
|
||||
uint8_t process_uart_get_eq_params(uint8_t *data, uint8_t *response, uint8_t response_size);
|
||||
uint8_t process_uart_reset_eq_params(uint8_t *data);
|
||||
uint8_t process_uart_get_eq_mode_count(uint8_t *response, uint8_t response_size);
|
||||
uint8_t process_uart_set_and_save_eq_mode(uint8_t *data);
|
||||
|
||||
|
||||
#endif
|
||||
void init_mode_info(void);
|
||||
|
||||
uint8_t reset_eq_params(uint8_t mode);
|
||||
|
||||
// 动态系数计算函数声明
|
||||
int calculate_current_mode_coefficients(uint32_t sample_rate, uint8_t mode);
|
||||
|
||||
// 串口EQ命令处理函数声明
|
||||
#endif //__HEADER_EQ_HANDLER__
|
||||
@@ -0,0 +1,143 @@
|
||||
#define DEBUG_PRINT_ENABLE 0
|
||||
#include "eq_coefficient_calculator.h"
|
||||
#include "biquad_standalone.h"
|
||||
#include <math.h>
|
||||
|
||||
#if 0 // DEBUG_PRINT_ENABLE
|
||||
#define DPRINTF(...) printf(__VA_ARGS__)
|
||||
#else
|
||||
#define DPRINTF(...)
|
||||
#endif
|
||||
|
||||
|
||||
// 系数计算函数
|
||||
int eq_calculate_coefficients_from_params(filter_params_t *params,
|
||||
uint32_t sample_rate,
|
||||
q2_30 coeffs[5],
|
||||
int *bshift) {
|
||||
|
||||
if (!params || !coeffs || !bshift) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 根据滤波器类型调用相应的biquad计算函数
|
||||
switch (params->type) {
|
||||
case FILTER_TYPE_BYPASS:
|
||||
eq_biquad_bypass(coeffs);
|
||||
*bshift = 0;
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_LOWPASS:
|
||||
eq_biquad_lowpass(coeffs,
|
||||
params->fc,
|
||||
(float)sample_rate,
|
||||
params->q);
|
||||
*bshift = 0;
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_HIGHPASS:
|
||||
eq_biquad_highpass(coeffs,
|
||||
params->fc,
|
||||
(float)sample_rate,
|
||||
params->q);
|
||||
*bshift = 0;
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_BANDPASS:
|
||||
case FILTER_TYPE_BANDSTOP:
|
||||
case FILTER_TYPE_NOTCH:
|
||||
case FILTER_TYPE_CONST_Q:
|
||||
// These filter types have been removed to save memory.
|
||||
// Fall through to bypass behavior.
|
||||
eq_biquad_bypass(coeffs);
|
||||
*bshift = 0;
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_ALLPASS:
|
||||
eq_biquad_allpass(coeffs,
|
||||
params->fc,
|
||||
(float)sample_rate,
|
||||
params->q);
|
||||
*bshift = 0;
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_PEAKING:
|
||||
*bshift = eq_biquad_peaking(coeffs,
|
||||
params->fc,
|
||||
(float)sample_rate,
|
||||
params->q,
|
||||
params->gain);
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_LOWSHELF:
|
||||
*bshift = eq_biquad_lowshelf(coeffs,
|
||||
params->fc,
|
||||
(float)sample_rate,
|
||||
params->q,
|
||||
params->gain);
|
||||
break;
|
||||
|
||||
case FILTER_TYPE_HIGHSHELF:
|
||||
*bshift = eq_biquad_highshelf(coeffs,
|
||||
params->fc,
|
||||
(float)sample_rate,
|
||||
params->q,
|
||||
params->gain);
|
||||
break;
|
||||
|
||||
default:
|
||||
// 默认使用bypass
|
||||
eq_biquad_bypass(coeffs);
|
||||
*bshift = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
#if 1 //DEBUG_PRINT_ENABLE == 1
|
||||
DPRINTF("--------------------------------\n");
|
||||
for(int i = 0; i < 5; i++) {
|
||||
if (coeffs[i] < 0) {
|
||||
DPRINTF("coeffs[%d]: -0x%08x\n", i, (unsigned int)(-coeffs[i]));
|
||||
} else {
|
||||
DPRINTF("coeffs[%d]: 0x%08x\n", i, (unsigned int)coeffs[i]);
|
||||
}
|
||||
}
|
||||
DPRINTF("--------------------------------\n");
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 批量计算所有滤波器的系数
|
||||
int eq_calculate_all_coefficients(eq_mode_data_t *eq_data,
|
||||
uint32_t sample_rate) {
|
||||
|
||||
if (!eq_data) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int total_bshift = 0;
|
||||
|
||||
// 计算每个滤波器的系数
|
||||
for (int i = 0; i < MAX_EQ_BANDS; i++) {
|
||||
q2_30 coeffs[5];
|
||||
int bshift;
|
||||
|
||||
if (eq_calculate_coefficients_from_params(&eq_data->bands[i],
|
||||
sample_rate, coeffs, &bshift) == 0) {
|
||||
// 存储计算出的系数
|
||||
for (int j = 0; j < 5; j++) {
|
||||
eq_data->filter.coef[j][i] = coeffs[j];
|
||||
}
|
||||
total_bshift += bshift;
|
||||
}
|
||||
}
|
||||
|
||||
// 更新总bshift
|
||||
eq_data->total_bshift = total_bshift;
|
||||
|
||||
#if DEBUG_PRINT_ENABLE == 1
|
||||
DPRINTF("total_bshift: %d\n", total_bshift);
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#ifndef EQ_COEFFICIENT_CALCULATOR_H
|
||||
#define EQ_COEFFICIENT_CALCULATOR_H
|
||||
|
||||
#include "eq.h"
|
||||
#include "biquad_standalone.h"
|
||||
|
||||
// 系数计算函数
|
||||
int eq_calculate_coefficients_from_params(filter_params_t *params,
|
||||
uint32_t sample_rate,
|
||||
q2_30 coeffs[5],
|
||||
int *bshift);
|
||||
|
||||
// 批量计算所有滤波器的系数
|
||||
int eq_calculate_all_coefficients(eq_mode_data_t *eq_data,
|
||||
uint32_t sample_rate);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
|
||||
|
||||
a = Analysis(
|
||||
['eq_designer_new.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
datas=[],
|
||||
hiddenimports=[],
|
||||
hookspath=[],
|
||||
hooksconfig={},
|
||||
runtime_hooks=[],
|
||||
excludes=[],
|
||||
noarchive=False,
|
||||
optimize=0,
|
||||
)
|
||||
pyz = PYZ(a.pure)
|
||||
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.datas,
|
||||
[],
|
||||
name='eq_designer_new',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=True,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=True,
|
||||
disable_windowed_traceback=False,
|
||||
argv_emulation=False,
|
||||
target_arch=None,
|
||||
codesign_identity=None,
|
||||
entitlements_file=None,
|
||||
)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,423 @@
|
||||
#ifndef __EQ_FLASH_STORAGE_H__
|
||||
#define __EQ_FLASH_STORAGE_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "eq.h"
|
||||
|
||||
// EQ Flash存储相关常量定义
|
||||
#define EQ_FLASH_MAGIC 0x45515041 // "EQPA" - EQ参数文件魔数
|
||||
#define EQ_FLASH_MAGIC_PARAMS 0x45515041 // "EQPA" - EQ参数文件魔数
|
||||
#define EQ_FLASH_VERSION 0x00020000 // 版本2.0.0 - 优化存储格式
|
||||
#define EQ_FLASH_MAX_SAMPLE_RATES 6 // 支持的采样率数量
|
||||
#define EQ_FLASH_MAX_MODES 10 // 最大模式数量
|
||||
#define EQ_FLASH_MAX_CHANNELS 2 // 最大通道数量
|
||||
|
||||
// 支持的采样率列表
|
||||
#define EQ_SAMPLE_RATES {44100, 48000, 88200, 96000, 176400, 192000}
|
||||
|
||||
// EQ参数文件头结构 (简化版本,去除采样率字段)
|
||||
typedef struct {
|
||||
uint32_t magic; // 魔数: 0x45515041 ("EQPA")
|
||||
uint32_t version; // 版本号
|
||||
uint8_t mode; // 模式号
|
||||
uint8_t channel; // 通道号
|
||||
uint16_t reserved; // 保留字段
|
||||
uint32_t data_size; // 数据大小
|
||||
uint32_t crc32; // CRC32校验
|
||||
} __attribute__((packed)) eq_file_header_t;
|
||||
|
||||
// 元数据结构已移除,简化存储系统
|
||||
|
||||
// EQ存储状态结构
|
||||
typedef struct {
|
||||
int is_initialized; // 是否已初始化 (0: 否, 1: 是)
|
||||
int has_flash_data; // Flash中是否有数据 (0: 否, 1: 是)
|
||||
uint32_t last_sync_time; // 最后同步时间
|
||||
uint32_t sync_count; // 同步次数
|
||||
uint32_t error_count; // 错误次数
|
||||
} eq_storage_status_t;
|
||||
|
||||
// 增益存储结构(只存储用户模式)
|
||||
typedef struct {
|
||||
uint32_t magic; // 魔数: 0x4551474E ("EQGN" - EQ Gain)
|
||||
uint32_t version; // 版本号
|
||||
uint32_t data_size; // 数据大小
|
||||
uint32_t crc32; // CRC32校验
|
||||
} __attribute__((packed)) eq_gain_header_t;
|
||||
|
||||
// 模式增益数据(只存储用户模式6-8)
|
||||
typedef struct {
|
||||
int32_t mode_gains[3]; // 用户模式增益数组:mode 6, 7, 8,每个4字节
|
||||
} __attribute__((packed)) eq_gain_data_t;
|
||||
|
||||
// 单个模式名称存储结构
|
||||
typedef struct {
|
||||
uint32_t magic; // 魔数: 0x45514E4D ("EQNM" - EQ Name)
|
||||
uint32_t version; // 版本号
|
||||
uint8_t mode; // 模式号
|
||||
uint8_t reserved[3]; // 保留字段
|
||||
uint32_t data_size; // 数据大小(16字节)
|
||||
uint32_t crc32; // CRC32校验
|
||||
} __attribute__((packed)) eq_name_header_t;
|
||||
|
||||
// 单个模式名称数据
|
||||
typedef struct {
|
||||
char mode_name[16]; // 模式名称,16字节
|
||||
} __attribute__((packed)) eq_name_data_t;
|
||||
|
||||
// 兼容旧格式的结构(保留用于向后兼容)
|
||||
typedef struct {
|
||||
uint32_t magic; // 魔数: 0x45514E47 ("EQNG" - EQ Name Gain)
|
||||
uint32_t version; // 版本号
|
||||
uint32_t data_size; // 数据大小
|
||||
uint32_t crc32; // CRC32校验
|
||||
} __attribute__((packed)) eq_gain_name_header_t;
|
||||
|
||||
// 模式增益和名称数据
|
||||
typedef struct {
|
||||
int32_t mode_gains[NUM_EQ_MODES]; // 模式增益数组,每个4字节
|
||||
char mode_names[NUM_EQ_MODES][16]; // 模式名称数组,每个16字节
|
||||
} __attribute__((packed)) eq_gain_name_data_t;
|
||||
|
||||
// 函数声明
|
||||
|
||||
/**
|
||||
* @brief 初始化EQ Flash存储系统
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_flash_init(void);
|
||||
|
||||
/**
|
||||
* @brief 反初始化EQ Flash存储系统
|
||||
*/
|
||||
void eq_flash_deinit(void);
|
||||
|
||||
// 注意:save all 和 load all 函数已移除,使用动态单参数存储系统
|
||||
|
||||
/**
|
||||
* @brief 从Flash加载指定模式的EQ参数
|
||||
* @param mode 模式号
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_flash_load_mode(uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief 保存指定模式的EQ参数到Flash
|
||||
* @param mode 模式号
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_flash_save_mode(uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief 同步指定模式参数到Flash(延迟写入)
|
||||
* @param mode 模式号
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_flash_sync_mode(uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief 同步所有待更新的参数到Flash
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_flash_sync_all(void);
|
||||
|
||||
/**
|
||||
* @brief 检查Flash中是否存在EQ参数数据
|
||||
* @return 1: 存在, 0: 不存在
|
||||
*/
|
||||
int eq_flash_has_data(void);
|
||||
|
||||
/**
|
||||
* @brief 获取EQ存储状态
|
||||
* @param status 状态结构指针
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_flash_get_status(eq_storage_status_t *status);
|
||||
|
||||
/**
|
||||
* @brief 清除Flash中的所有EQ参数数据
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_flash_clear_all(void);
|
||||
|
||||
/**
|
||||
* @brief 验证EQ参数文件完整性
|
||||
* @param mode 模式号
|
||||
* @return 1: 完整, 0: 损坏
|
||||
*/
|
||||
int eq_flash_verify_mode(uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief 获取文件路径
|
||||
* @param mode 模式号
|
||||
* @param channel 通道号
|
||||
* @param path 输出路径缓冲区
|
||||
* @param max_len 缓冲区最大长度
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_flash_get_file_path(uint8_t mode, uint8_t channel,
|
||||
char *path, size_t max_len);
|
||||
|
||||
/**
|
||||
* @brief 计算CRC32校验值
|
||||
* @param data 数据指针
|
||||
* @param len 数据长度
|
||||
* @return CRC32值
|
||||
*/
|
||||
uint32_t eq_flash_calculate_crc32(const uint8_t *data, size_t len);
|
||||
|
||||
/**
|
||||
* @brief 检查是否需要同步参数到Flash
|
||||
* @return 1: 需要同步, 0: 不需要
|
||||
*/
|
||||
int eq_flash_needs_sync(void);
|
||||
|
||||
/**
|
||||
* @brief 标记参数已修改,需要同步
|
||||
* @param mode 模式号
|
||||
*/
|
||||
void eq_flash_mark_dirty(uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief 检查滤波器是否为默认值(bypass)
|
||||
* @param band 滤波器参数
|
||||
* @return 1: 是默认值, 0: 不是默认值
|
||||
*/
|
||||
int is_filter_bypass(const filter_params_t *band);
|
||||
|
||||
/**
|
||||
* @brief 从EQ数据中提取非默认滤波器到Flash存储格式
|
||||
* @param eq_data 源EQ数据
|
||||
* @param flash_data 目标Flash存储数据
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int extract_active_filters(const eq_mode_data_t *eq_data, eq_flash_data_t *flash_data);
|
||||
|
||||
/**
|
||||
* @brief 从Flash存储格式恢复EQ数据
|
||||
* @param flash_data 源Flash存储数据
|
||||
* @param eq_data 目标EQ数据
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int restore_eq_from_flash(const eq_flash_data_t *flash_data, eq_mode_data_t *eq_data);
|
||||
|
||||
/**
|
||||
* @brief 实时计算滤波器系数
|
||||
* @param eq_data EQ数据
|
||||
* @param sample_rate 采样率
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int calculate_filter_coefficients(eq_mode_data_t *eq_data, uint32_t sample_rate);
|
||||
|
||||
// ==================== 单参数动态存储系统 ====================
|
||||
|
||||
/**
|
||||
* @brief 初始化单参数存储数据库
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_single_param_database_init(void);
|
||||
|
||||
/**
|
||||
* @brief 处理0x8c/0x8d命令的单参数变化
|
||||
* @param data 接收到的数据
|
||||
* @param len 数据长度
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_process_single_param_change(uint32_t sample_rate, uint8_t mode, uint8_t channel, uint8_t band_index, filter_params_t *band);
|
||||
|
||||
/**
|
||||
* @brief 比较单个参数是否不同
|
||||
* @param old_params 旧参数
|
||||
* @param new_params 新参数
|
||||
* @return 1: 不同, 0: 相同
|
||||
*/
|
||||
int eq_single_params_different(const filter_params_t *old_params, const filter_params_t *new_params);
|
||||
|
||||
/**
|
||||
* @brief 添加单个参数变化到数据库
|
||||
* @param sample_rate 采样率
|
||||
* @param mode 模式
|
||||
* @param channel 通道
|
||||
* @param band_index 滤波器索引
|
||||
* @param new_params 新参数
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_add_single_param(uint32_t sample_rate, uint8_t mode, uint8_t channel,
|
||||
uint8_t band_index, const filter_params_t *new_params);
|
||||
|
||||
/**
|
||||
* @brief 保存单个参数到Flash
|
||||
* @param sample_rate 采样率
|
||||
* @param mode 模式
|
||||
* @param channel 通道
|
||||
* @param band_index 滤波器索引
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_save_single_param(uint32_t sample_rate, uint8_t mode, uint8_t channel, uint8_t band_index);
|
||||
|
||||
/**
|
||||
* @brief 从Flash加载单个参数
|
||||
* @param sample_rate 采样率
|
||||
* @param mode 模式
|
||||
* @param channel 通道
|
||||
* @param band_index 滤波器索引
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_load_single_param(uint32_t sample_rate, uint8_t mode, uint8_t channel, uint8_t band_index);
|
||||
|
||||
/**
|
||||
* @brief 保存所有脏参数到Flash(只保存EQ参数,不包括增益和名称)
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_save_dirty_params(void);
|
||||
|
||||
/**
|
||||
* @brief 保存脏的增益到Flash
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_save_dirty_gain(void);
|
||||
|
||||
/**
|
||||
* @brief 保存脏的模式名称到Flash
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_save_dirty_names(void);
|
||||
|
||||
/**
|
||||
* @brief 保存脏的增益和模式名称到Flash(兼容旧接口)
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_save_dirty_gain_and_names(void);
|
||||
|
||||
/**
|
||||
* @brief 保存用户模式的增益到Flash(只保存用户模式6-8)
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_save_gain(void);
|
||||
|
||||
/**
|
||||
* @brief 保存单个用户模式的名称到Flash(只有与初始值不同且非空才保存)
|
||||
* @param mode 模式号(必须是用户模式6-8)
|
||||
* @return 0: 成功, -1: 失败, 1: 跳过(与初始值相同或为空)
|
||||
*/
|
||||
int eq_save_name(uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief 从Flash加载用户模式的增益
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_load_gain(void);
|
||||
|
||||
/**
|
||||
* @brief 从Flash加载单个用户模式的名称
|
||||
* @param mode 模式号(必须是用户模式6-8)
|
||||
* @return 0: 成功, -1: 失败(文件不存在或错误)
|
||||
*/
|
||||
int eq_load_name(uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief 保存增益和模式名称到Flash(兼容旧接口,内部调用新函数)
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_save_gain_and_names(void);
|
||||
|
||||
/**
|
||||
* @brief 从Flash加载增益和模式名称(兼容旧接口,内部调用新函数)
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_load_gain_and_names(void);
|
||||
|
||||
/**
|
||||
* @brief 标记增益为脏(需要保存)
|
||||
*/
|
||||
void eq_mark_gain_dirty(void);
|
||||
|
||||
/**
|
||||
* @brief 标记模式名称为脏(需要保存)
|
||||
*/
|
||||
void eq_mark_name_dirty(void);
|
||||
|
||||
/**
|
||||
* @brief 标记增益和模式名称为脏(需要保存)(兼容旧接口)
|
||||
*/
|
||||
void eq_mark_gain_name_dirty(void);
|
||||
|
||||
/**
|
||||
* @brief 删除Flash中的EQ参数文件
|
||||
* @param mode 模式号 (0-9, 0xFF表示所有模式)
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int delete_flash_eq_params(uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief 删除Flash中的增益和模式名称文件
|
||||
* @param mode 模式号 (0-9, 0xFF表示所有模式)
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int delete_flash_gain_and_names(uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief 恢复默认EQ参数
|
||||
* @param mode 模式号 (0-9, 0xFF表示所有模式)
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int restore_default_eq_params(uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief 系统开机时加载所有参数并计算系数
|
||||
* @param sample_rate 采样率
|
||||
* @param mode 模式
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_load_all_params_and_calculate_coefficients(uint32_t sample_rate, uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief 获取单参数存储统计
|
||||
* @param stats 输出统计信息
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_get_single_param_stats(eq_single_param_database_t *stats);
|
||||
|
||||
/**
|
||||
* @brief 清空单参数存储数据库
|
||||
* @return 0: 成功, -1: 失败
|
||||
*/
|
||||
int eq_clear_single_param_database(void);
|
||||
|
||||
/**
|
||||
* @brief 保存EQ使能状态到Flash(独立文件存储,与模式存储完全分离)
|
||||
* @param enable EQ使能状态 (0=禁用, 1=启用)
|
||||
* @return 0: 成功, -1: 失败
|
||||
*
|
||||
* 改动原因:将eq_enable存储独立为单独文件(eq_enable),与模式存储完全分离,互不影响
|
||||
*/
|
||||
int eq_flash_save_eq_enable(uint8_t enable);
|
||||
|
||||
/**
|
||||
* @brief 从Flash加载EQ使能状态(独立文件加载,与模式加载完全分离)
|
||||
* @return 使能状态值: 成功(0或1), -1: 失败
|
||||
*
|
||||
* 改动原因:从独立文件(eq_enable)加载eq_enable,与模式加载完全分离,互不影响
|
||||
*/
|
||||
int eq_flash_load_eq_enable(void);
|
||||
|
||||
/**
|
||||
* @brief 保存当前EQ模式到Flash(独立文件存储,与使能状态存储完全分离)
|
||||
* @param mode 模式值 (0-9)
|
||||
* @return 0: 成功, -1: 失败
|
||||
*
|
||||
* 改动原因:将模式存储独立为单独文件(cur_mode),与eq_enable存储完全分离,互不影响
|
||||
*/
|
||||
int eq_flash_save_current_mode(uint8_t mode);
|
||||
|
||||
/**
|
||||
* @brief 从Flash加载当前EQ模式(独立文件加载,与使能状态加载完全分离)
|
||||
* @return 模式值: 成功(0-9), -1: 失败
|
||||
*
|
||||
* 改动原因:从独立文件(cur_mode)加载模式,与eq_enable加载完全分离,互不影响
|
||||
* 注意:此函数同时加载模式和使能状态(从两个独立文件),用于初始化
|
||||
*/
|
||||
int eq_flash_load_current_mode(void);
|
||||
|
||||
#endif // __EQ_FLASH_STORAGE_H__
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,296 @@
|
||||
#include "dsp/td_block_fir.h"
|
||||
|
||||
int32_t __attribute__((aligned (8))) coefs_ex3d_0[1024] = {
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 536870912
|
||||
};
|
||||
td_block_fir_filter_t td_block_fir_filter_ex3d_0 = {
|
||||
.coefs = coefs_ex3d_0,
|
||||
.block_count = 128,
|
||||
.accu_shr = 0,
|
||||
.accu_shl = -1,
|
||||
};
|
||||
|
||||
td_block_fir_filter_t td_block_fir_filter_ex3d_1 = {
|
||||
.coefs = coefs_ex3d_0,
|
||||
.block_count = 128,
|
||||
.accu_shr = 0,
|
||||
.accu_shl = -1,
|
||||
};
|
||||
|
||||
td_block_fir_filter_t td_block_fir_filter_ex3d_2 = {
|
||||
.coefs = coefs_ex3d_0,
|
||||
.block_count = 128,
|
||||
.accu_shr = 0,
|
||||
.accu_shl = -1,
|
||||
};
|
||||
|
||||
td_block_fir_filter_t td_block_fir_filter_ex3d_3 = {
|
||||
.coefs = coefs_ex3d_0,
|
||||
.block_count = 128,
|
||||
.accu_shr = 0,
|
||||
.accu_shl = -1,
|
||||
};
|
||||
|
||||
//This is the count of int32_t words to allocate for one data channel.
|
||||
//i.e. int32_t channel_data[ex3d_0_DATA_BUFFER_ELEMENTS] = { 0 };
|
||||
#define ex3d_0_DATA_BUFFER_ELEMENTS (1040)
|
||||
|
||||
#define ex3d_0_TD_BLOCK_LENGTH (8)
|
||||
#define ex3d_0_BLOCK_COUNT (128)
|
||||
#define ex3d_0_FRAME_ADVANCE (8)
|
||||
#define ex3d_0_FRAME_OVERLAP (0)
|
||||
@@ -0,0 +1,909 @@
|
||||
# EX3D HID通信协议详细文档
|
||||
|
||||
## 1. 总体框架
|
||||
|
||||
### 1.1 协议概述
|
||||
该协议使用HID (Human Interface Device) 协议进行主机与设备之间的通信。协议支持EX3D(3D音频扩展)参数设置、读取等功能。
|
||||
|
||||
### 1.2 命令格式说明
|
||||
|
||||
EX3D命令使用特殊的命令格式:
|
||||
- **基础命令码**: 0x80-0x94 (定义在PlbkCmdCode枚举中)
|
||||
- **命令修饰符**:
|
||||
- `CMD_SET(cmd)`: 清除第9位(0x0100),用于设置命令
|
||||
- `CMD_GET(cmd)`: 设置第9位(0x0100),用于读取命令
|
||||
- `CMD_MASK`: 提取基础命令码的掩码(~0x0F00)
|
||||
|
||||
- **命令结构**:
|
||||
- 设置命令: `基础命令码 & ~0x0100` (例如: CMD_ONOFF = 0x82, SET命令 = 0x82)
|
||||
- 读取命令: `基础命令码 | 0x0100` (例如: CMD_ONOFF = 0x82, GET命令 = 0x182)
|
||||
|
||||
### 1.3 数据包格式
|
||||
- **数据包大小**: 最大64字节 (1字节Report ID + 63字节数据)
|
||||
- **数据对齐**: 使用32位(unsigned)对齐,数据从RcvData[4]开始,即pRcvBuf[0]开始
|
||||
- **字节序**: 小端序 (Little Endian)
|
||||
|
||||
## 2. 详细命令说明
|
||||
|
||||
### 2.1 命令列表
|
||||
|
||||
| 基础命令码 | 命令名称 | SET命令码 | GET命令码 | 功能 | 方向 |
|
||||
|-----------|----------|-----------|-----------|------|------|
|
||||
| 0x80 | CMD_CH_NUM | - | 0x180 | 获取通道数量 | 主机→设备 |
|
||||
| 0x81 | CMD_OPEN | 0x81 | - | 打开EX3D | 主机→设备 |
|
||||
| 0x82 | CMD_ONOFF | 0x82 | 0x182 | 设置/获取EX3D开关 | 主机↔设备 |
|
||||
| 0x83 | CMD_ANGLE | 0x83 | 0x183 | 设置/获取角度 | 主机↔设备 |
|
||||
| 0x84 | CMD_SOUND_FIELD | 0x84 | 0x184 | 设置/获取声场模式 | 主机↔设备 |
|
||||
| 0x85 | CMD_MUTE | 0x85 | 0x185 | 设置/获取静音 | 主机↔设备 |
|
||||
| 0x86 | CMD_ON_GAIN | 0x86 | 0x186 | 设置/获取开启增益 | 主机↔设备 |
|
||||
| 0x87 | CMD_LMT_THRESHOLD | 0x87 | 0x187 | 设置/获取限制器阈值 | 主机↔设备 |
|
||||
| 0x88 | CMD_UPMIX | 0x88 | 0x188 | 设置/获取上混 | 主机↔设备 |
|
||||
| 0x89 | CMD_LFE | 0x89 | 0x189 | 设置/获取LFE增益 | 主机↔设备 |
|
||||
| 0x8A | CMD_OFF_GAIN | 0x8A | 0x18A | 设置/获取关闭增益 | 主机↔设备 |
|
||||
| 0x8B | CMD_SOUND_FIELD_NUM | - | 0x18B | 获取声场模式数量 | 主机→设备 |
|
||||
| 0x8C | CMD_SOUND_FIELD_NAME | - | 0x18C | 获取声场模式名称 | 主机→设备 |
|
||||
| 0x8D | CMD_LEVEL | - | 0x18D | 获取电平 | 主机→设备 |
|
||||
| 0x8E | CMD_LMT_ATTACKK_TIME | 0x8E | 0x18E | 设置/获取限制器攻击时间 | 主机↔设备 |
|
||||
| 0x8F | CMD_LMT_RELEASE_TIME | 0x8F | 0x18F | 设置/获取限制器释放时间 | 主机↔设备 |
|
||||
| 0x90 | CMD_TEST_CANCEL | 0x90 | - | 取消测试 | 主机→设备 |
|
||||
| 0x91 | CMD_TEST_STEP | 0x91 | - | 测试步骤 | 主机→设备 |
|
||||
| 0x92 | CMD_TEST_ROTATE | 0x92 | - | 测试旋转 | 主机→设备 |
|
||||
| 0x93 | CMD_EXPAND_GAIN | 0x93 | 0x193 | 设置/获取扩展增益 | 主机↔设备 |
|
||||
| 0x94 | CMD_REDUCE_GAIN | 0x94 | 0x194 | 设置/获取减少增益 | 主机↔设备 |
|
||||
|
||||
### 2.2 数据包结构
|
||||
|
||||
#### 通用请求数据包格式
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 保留 | 保留字节(跳过)
|
||||
4-7 | 4 | uint32 | 命令码 (包含SET/GET标志)
|
||||
8-11 | 4 | uint32 | 参数1 (根据命令不同而不同)
|
||||
12-15 | 4 | uint32 | 参数2 (根据命令不同而不同)
|
||||
... | ... | ... | 其他参数
|
||||
```
|
||||
|
||||
#### 通用响应数据包格式
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 保留 | 保留字节(跳过)
|
||||
4-7 | 4 | uint32 | 命令码 (回显)
|
||||
8-11 | 4 | uint32 | 返回值/参数1
|
||||
12-15 | 4 | uint32 | 返回值/参数2
|
||||
... | ... | ... | 其他返回值
|
||||
```
|
||||
|
||||
### 2.3 详细命令说明
|
||||
|
||||
#### 2.3.1 CMD_CH_NUM (0x80) - 获取通道数量
|
||||
**功能**: 获取USB音频输出通道数量
|
||||
**方向**: 主机→设备
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x180 = CMD_GET(CMD_CH_NUM))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x180,回显)
|
||||
8-11 | 4 | uint32 | 通道数量 (NUM_USB_CHAN_OUT)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.2 CMD_OPEN (0x81) - 打开EX3D
|
||||
**功能**: 打开EX3D系统
|
||||
**方向**: 主机→设备
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x81 = CMD_SET(CMD_OPEN))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x81,回显)
|
||||
8-63 | 56 | 0x00 | 保留字节(无返回值)
|
||||
```
|
||||
|
||||
#### 2.3.3 CMD_ONOFF (0x82) - 设置/获取EX3D开关
|
||||
**功能**: 设置或获取EX3D开关状态
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x82):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x82 = CMD_SET(CMD_ONOFF))
|
||||
8-11 | 4 | uint32 | 开关值 (0=关闭, 1=开启)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x82,回显)
|
||||
8-63 | 56 | 0x00 | 保留字节(无返回值)
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x182):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x182 = CMD_GET(CMD_ONOFF))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x182,回显)
|
||||
8-11 | 4 | uint32 | 当前开关状态 (0=关闭, 1=开启)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.4 CMD_ANGLE (0x83) - 设置/获取角度
|
||||
**功能**: 设置或获取通道的角度(垂直角度和水平角度)
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x83):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x83 = CMD_SET(CMD_ANGLE))
|
||||
8-11 | 4 | uint32 | 通道号 (如果 >= NUM_USB_CHAN_OUT,表示设置所有通道)
|
||||
12-15 | 4 | uint32 | 角度值1 (单通道) 或 角度值[0] (多通道)
|
||||
16-19 | 4 | uint32 | 角度值2 (多通道,可选)
|
||||
... | ... | ... | 其他通道角度值(最多NUM_USB_CHAN_OUT个)
|
||||
```
|
||||
**角度值格式**: `(VAngle << 16) | HAngle`
|
||||
- VAngle: 垂直角度 (0-180度,高16位)
|
||||
- HAngle: 水平角度 (0-359度,低16位)
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x83,回显)
|
||||
8-63 | 56 | 0x00 | 保留字节(无返回值)
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x183):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x183 = CMD_GET(CMD_ANGLE))
|
||||
8-11 | 4 | uint32 | 通道号 (如果 >= NUM_USB_CHAN_OUT,表示获取所有通道)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x183,回显)
|
||||
8-11 | 4 | uint32 | 角度值 (单通道) 或 角度值[0] (多通道)
|
||||
12-15 | 4 | uint32 | 角度值[1] (多通道,可选)
|
||||
... | ... | ... | 其他通道角度值(最多NUM_USB_CHAN_OUT个)
|
||||
```
|
||||
**角度值格式**: `(VAngle << 16) | HAngle`
|
||||
|
||||
#### 2.3.5 CMD_SOUND_FIELD (0x84) - 设置/获取声场模式
|
||||
**功能**: 设置或获取当前声场模式
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x84):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x84 = CMD_SET(CMD_SOUND_FIELD))
|
||||
8-11 | 4 | uint32 | 声场模式索引 (0到EX3D_SF_NUM-1)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x84,回显)
|
||||
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=索引无效, 其他=成功)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x184):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x184 = CMD_GET(CMD_SOUND_FIELD))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x184,回显)
|
||||
8-11 | 4 | uint32 | 当前声场模式索引 (或0)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.6 CMD_MUTE (0x85) - 设置/获取静音
|
||||
**功能**: 设置或获取通道的静音状态
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x85):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x85 = CMD_SET(CMD_MUTE))
|
||||
8-11 | 4 | uint32 | 通道号 (如果 >= NUM_USB_CHAN_OUT,表示设置所有通道)
|
||||
12-15 | 4 | uint32 | 静音值1 (单通道) 或 静音值[0] (多通道,0=不静音, 1=静音)
|
||||
16-19 | 4 | uint32 | 静音值2 (多通道,可选)
|
||||
... | ... | ... | 其他通道静音值(最多NUM_USB_CHAN_OUT个)
|
||||
```
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x85,回显)
|
||||
8-63 | 56 | 0x00 | 保留字节(无返回值)
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x185):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x185 = CMD_GET(CMD_MUTE))
|
||||
8-11 | 4 | uint32 | 通道号 (如果 >= NUM_USB_CHAN_OUT,表示获取所有通道)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x185,回显)
|
||||
8-11 | 4 | uint32 | 静音值 (单通道) 或 静音值[0] (多通道)
|
||||
12-15 | 4 | uint32 | 静音值[1] (多通道,可选)
|
||||
... | ... | ... | 其他通道静音值(最多NUM_USB_CHAN_OUT个)
|
||||
```
|
||||
|
||||
#### 2.3.7 CMD_ON_GAIN (0x86) - 设置/获取开启增益
|
||||
**功能**: 设置或获取EX3D开启时的增益值
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x86):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x86 = CMD_SET(CMD_ON_GAIN))
|
||||
8-11 | 4 | int32 | 增益值 (范围-100到0 dB,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x86,回显)
|
||||
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x186):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x186 = CMD_GET(CMD_ON_GAIN))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x186,回显)
|
||||
8-11 | 4 | int32 | 当前开启增益值 (范围-100到0 dB,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.8 CMD_LMT_THRESHOLD (0x87) - 设置/获取限制器阈值
|
||||
**功能**: 设置或获取限制器阈值
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x87):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x87 = CMD_SET(CMD_LMT_THRESHOLD))
|
||||
8-11 | 4 | int32 | 阈值 (范围-35到0 dB,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x87,回显)
|
||||
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x187):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x187 = CMD_GET(CMD_LMT_THRESHOLD))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x187,回显)
|
||||
8-11 | 4 | int32 | 当前限制器阈值 (范围-35到0 dB,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.9 CMD_UPMIX (0x88) - 设置/获取上混
|
||||
**功能**: 设置或获取上混状态
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x88):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x88 = CMD_SET(CMD_UPMIX))
|
||||
8-11 | 4 | uint32 | 上混值 (0=关闭, 1=开启)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x88,回显)
|
||||
8-63 | 56 | 0x00 | 保留字节(无返回值)
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x188):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x188 = CMD_GET(CMD_UPMIX))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x188,回显)
|
||||
8-11 | 4 | uint32 | 当前上混状态 (0=关闭, 1=开启)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.10 CMD_LFE (0x89) - 设置/获取LFE增益
|
||||
**功能**: 设置或获取LFE(低频效果)增益
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x89):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x89 = CMD_SET(CMD_LFE))
|
||||
8-11 | 4 | int32 | 增益值 (范围-100到0 dB,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x89,回显)
|
||||
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x189):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x189 = CMD_GET(CMD_LFE))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x189,回显)
|
||||
8-11 | 4 | int32 | 当前LFE增益值 (范围-100到0 dB,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.11 CMD_OFF_GAIN (0x8A) - 设置/获取关闭增益
|
||||
**功能**: 设置或获取EX3D关闭时的增益值
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x8A):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x8A = CMD_SET(CMD_OFF_GAIN))
|
||||
8-11 | 4 | int32 | 增益值 (范围-100到0 dB,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x8A,回显)
|
||||
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x18A):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x18A = CMD_GET(CMD_OFF_GAIN))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x18A,回显)
|
||||
8-11 | 4 | int32 | 当前关闭增益值 (范围-100到0 dB,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.12 CMD_SOUND_FIELD_NUM (0x8B) - 获取声场模式数量
|
||||
**功能**: 获取可用的声场模式数量
|
||||
**方向**: 主机→设备
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x18B = CMD_GET(CMD_SOUND_FIELD_NUM))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x18B,回显)
|
||||
8-11 | 4 | uint32 | 声场模式数量 (EX3D_SF_NUM)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.13 CMD_SOUND_FIELD_NAME (0x8C) - 获取声场模式名称
|
||||
**功能**: 获取指定声场模式的名称
|
||||
**方向**: 主机→设备
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x18C = CMD_GET(CMD_SOUND_FIELD_NAME))
|
||||
8-11 | 4 | uint32 | 声场模式索引
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x18C,回显)
|
||||
8-11 | 4 | uint32 | 名称长度 (如果索引无效则为0xFFFFFFFF)
|
||||
12-15 | 4 | char | 名称字符[0-3] (UTF-8编码,如果索引有效)
|
||||
16-19 | 4 | char | 名称字符[4-7] (UTF-8编码,可选)
|
||||
... | ... | ... | 其他名称字符(最多16字节)
|
||||
```
|
||||
**注意**: 如果索引无效,位置8-11返回0xFFFFFFFF,后续字节为0x00
|
||||
|
||||
#### 2.3.14 CMD_LEVEL (0x8D) - 获取电平
|
||||
**功能**: 获取通道的电平值
|
||||
**方向**: 主机→设备
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x18D = CMD_GET(CMD_LEVEL))
|
||||
8-11 | 4 | uint32 | 通道数量
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x18D,回显)
|
||||
8-11 | 4 | float | 电平值[0] (通道0的电平值,IEEE 754格式,小端序)
|
||||
12-15 | 4 | float | 电平值[1] (通道1的电平值,可选)
|
||||
... | ... | ... | 其他通道电平值(最多NUM_USB_CHAN_OUT个,每个4字节float)
|
||||
```
|
||||
|
||||
#### 2.3.15 CMD_LMT_ATTACKK_TIME (0x8E) - 设置/获取限制器攻击时间
|
||||
**功能**: 设置或获取限制器攻击时间
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x8E):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x8E = CMD_SET(CMD_LMT_ATTACKK_TIME))
|
||||
8-11 | 4 | uint32 | 攻击时间 (范围0到10,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x8E,回显)
|
||||
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x18E):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x18E = CMD_GET(CMD_LMT_ATTACKK_TIME))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x18E,回显)
|
||||
8-11 | 4 | uint32 | 当前限制器攻击时间 (范围0到10,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.16 CMD_LMT_RELEASE_TIME (0x8F) - 设置/获取限制器释放时间
|
||||
**功能**: 设置或获取限制器释放时间
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x8F):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x8F = CMD_SET(CMD_LMT_RELEASE_TIME))
|
||||
8-11 | 4 | uint32 | 释放时间 (范围0到100,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x8F,回显)
|
||||
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x18F):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x18F = CMD_GET(CMD_LMT_RELEASE_TIME))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x18F,回显)
|
||||
8-11 | 4 | uint32 | 当前限制器释放时间 (范围0到100,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.17 CMD_EXPAND_GAIN (0x93) - 设置/获取扩展增益
|
||||
**功能**: 设置或获取扩展增益值
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x93):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x93 = CMD_SET(CMD_EXPAND_GAIN))
|
||||
8-11 | 4 | int32 | 增益值 (范围0到20,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x93,回显)
|
||||
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x193):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x193 = CMD_GET(CMD_EXPAND_GAIN))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x193,回显)
|
||||
8-11 | 4 | int32 | 当前扩展增益值 (范围0到20,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.18 CMD_REDUCE_GAIN (0x94) - 设置/获取减少增益
|
||||
**功能**: 设置或获取减少增益值
|
||||
**方向**: 主机↔设备
|
||||
|
||||
**SET命令请求数据包格式** (0x94):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x94 = CMD_SET(CMD_REDUCE_GAIN))
|
||||
8-11 | 4 | int32 | 增益值 (范围-20到0,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**SET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x94,回显)
|
||||
8-11 | 4 | uint32 | 状态码 (0xFFFFFFFF=参数超出范围, 其他=成功)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令请求数据包格式** (0x194):
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x194 = CMD_GET(CMD_REDUCE_GAIN))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**GET命令响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x194,回显)
|
||||
8-11 | 4 | int32 | 当前减少增益值 (范围-20到0,小端序)
|
||||
12-63 | 52 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
#### 2.3.19 CMD_TEST_CANCEL (0x90) - 取消测试
|
||||
**功能**: 取消EX3D测试
|
||||
**方向**: 主机→设备
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x90 = CMD_SET(CMD_TEST_CANCEL))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x90,回显)
|
||||
8-63 | 56 | 0x00 | 保留字节(无返回值)
|
||||
```
|
||||
|
||||
#### 2.3.20 CMD_TEST_STEP (0x91) - 测试步骤
|
||||
**功能**: 执行EX3D测试步骤
|
||||
**方向**: 主机→设备
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x91 = CMD_SET(CMD_TEST_STEP))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x91,回显)
|
||||
8-63 | 56 | 0x00 | 保留字节(无返回值)
|
||||
```
|
||||
|
||||
#### 2.3.21 CMD_TEST_ROTATE (0x92) - 测试旋转
|
||||
**功能**: 执行EX3D测试旋转
|
||||
**方向**: 主机→设备
|
||||
**请求数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x92 = CMD_SET(CMD_TEST_ROTATE))
|
||||
8-63 | 56 | 0x00 | 保留字节
|
||||
```
|
||||
|
||||
**响应数据包格式**:
|
||||
```
|
||||
字节位置 | 长度 | 内容 | 描述
|
||||
---------|------|------|------
|
||||
0 | 1 | 0x01 | Report ID
|
||||
1-3 | 3 | 0x00 | 保留字节
|
||||
4-7 | 4 | uint32 | 命令码 (0x92,回显)
|
||||
8-63 | 56 | 0x00 | 保留字节(无返回值)
|
||||
```
|
||||
|
||||
## 3. 注意事项
|
||||
|
||||
1. **数据对齐**: 所有数据使用32位(unsigned)对齐,从RcvData[4]开始
|
||||
2. **命令码格式**: SET命令清除第9位,GET命令设置第9位
|
||||
3. **错误处理**: 当参数超出范围时,返回0xFFFFFFFF表示错误
|
||||
4. **多通道处理**: ANGLE和MUTE命令支持单通道或多通道批量设置
|
||||
5. **字节序**: 所有多字节数据使用小端序
|
||||
6. **字符串编码**: 字符串使用UTF-8编码
|
||||
|
||||
## 4. 实现参考
|
||||
|
||||
参考文件: `sw_usb_audio/app_usb_aud_phaten_golden/src/extensions/dsp.c`
|
||||
- 函数: `hid_receive_task_in_c()`
|
||||
- 行号: 269-598
|
||||
|
||||
@@ -0,0 +1,324 @@
|
||||
#!/usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
滤波器工具类
|
||||
包含双二阶滤波器计算器和各种滤波器类型的系数计算函数
|
||||
"""
|
||||
|
||||
import math
|
||||
import numpy as np
|
||||
from typing import Dict, List, Union
|
||||
|
||||
class BiquadFilterCalculator:
|
||||
"""双二阶滤波器计算器"""
|
||||
def __init__(self):
|
||||
self.coefficients = {
|
||||
'a0': 0.0,
|
||||
'a1': 0.0,
|
||||
'a2': 0.0,
|
||||
'b1': 0.0,
|
||||
'b2': 0.0
|
||||
}
|
||||
|
||||
def calculate(self, filter_type: str, Fc: float, Fs: float, Q: float, peak_gain: float, bandwidth: float = None) -> Dict[str, float]:
|
||||
"""
|
||||
计算滤波器系数
|
||||
:param filter_type: 滤波器类型
|
||||
:param Fc: 截止频率
|
||||
:param Fs: 采样率
|
||||
:param Q: 品质因数
|
||||
:param peak_gain: 峰值增益(dB)
|
||||
:return: 滤波器系数字典
|
||||
"""
|
||||
V = math.pow(10, abs(peak_gain) / 20)
|
||||
K = math.tan(math.pi * Fc / Fs)
|
||||
norm = 0.0
|
||||
|
||||
filter_type = filter_type.lower()
|
||||
|
||||
if filter_type == "lowpass":
|
||||
norm = 1 / (1 + K / Q + K * K)
|
||||
self.coefficients['a0'] = K * K * norm
|
||||
self.coefficients['a1'] = 2 * self.coefficients['a0']
|
||||
self.coefficients['a2'] = self.coefficients['a0']
|
||||
self.coefficients['b1'] = 2 * (K * K - 1) * norm
|
||||
self.coefficients['b2'] = (1 - K / Q + K * K) * norm
|
||||
|
||||
elif filter_type == "highpass":
|
||||
norm = 1 / (1 + K / Q + K * K)
|
||||
self.coefficients['a0'] = 1 * norm
|
||||
self.coefficients['a1'] = -2 * self.coefficients['a0']
|
||||
self.coefficients['a2'] = self.coefficients['a0']
|
||||
self.coefficients['b1'] = 2 * (K * K - 1) * norm
|
||||
self.coefficients['b2'] = (1 - K / Q + K * K) * norm
|
||||
|
||||
elif filter_type == "bandpass":
|
||||
# 使用lib_audio_dsp中biquad.c的算法
|
||||
# 使用bandwidth参数,如果没有提供则使用Q作为近似值
|
||||
bw = bandwidth if bandwidth is not None else Q
|
||||
w0 = 2.0 * math.pi * Fc / Fs
|
||||
sin_w0 = math.sin(w0)
|
||||
alpha = sin_w0 * math.sinh(math.log(2) / 2.0 * bw * w0 / sin_w0)
|
||||
|
||||
self.coefficients['a0'] = alpha
|
||||
self.coefficients['a1'] = 0
|
||||
self.coefficients['a2'] = -alpha
|
||||
self.coefficients['b1'] = -2.0 * math.cos(w0)
|
||||
self.coefficients['b2'] = 1.0 - alpha
|
||||
|
||||
# 归一化
|
||||
a0 = 1.0 + alpha
|
||||
inv_a0 = 1.0 / a0
|
||||
self.coefficients['a0'] *= inv_a0
|
||||
self.coefficients['a1'] *= inv_a0
|
||||
self.coefficients['a2'] *= inv_a0
|
||||
self.coefficients['b1'] *= inv_a0
|
||||
self.coefficients['b2'] *= inv_a0
|
||||
|
||||
elif filter_type == "notch":
|
||||
norm = 1 / (1 + K / Q + K * K)
|
||||
self.coefficients['a0'] = (1 + K * K) * norm
|
||||
self.coefficients['a1'] = 2 * (K * K - 1) * norm
|
||||
self.coefficients['a2'] = self.coefficients['a0']
|
||||
self.coefficients['b1'] = self.coefficients['a1']
|
||||
self.coefficients['b2'] = (1 - K / Q + K * K) * norm
|
||||
|
||||
elif filter_type == "peak":
|
||||
if peak_gain >= 0:
|
||||
norm = 1 / (1 + 1/Q * K + K * K)
|
||||
self.coefficients['a0'] = (1 + V/Q * K + K * K) * norm
|
||||
self.coefficients['a1'] = 2 * (K * K - 1) * norm
|
||||
self.coefficients['a2'] = (1 - V/Q * K + K * K) * norm
|
||||
self.coefficients['b1'] = self.coefficients['a1']
|
||||
self.coefficients['b2'] = (1 - 1/Q * K + K * K) * norm
|
||||
else:
|
||||
norm = 1 / (1 + V/Q * K + K * K)
|
||||
self.coefficients['a0'] = (1 + 1/Q * K + K * K) * norm
|
||||
self.coefficients['a1'] = 2 * (K * K - 1) * norm
|
||||
self.coefficients['a2'] = (1 - 1/Q * K + K * K) * norm
|
||||
self.coefficients['b1'] = self.coefficients['a1']
|
||||
self.coefficients['b2'] = (1 - V/Q * K + K * K) * norm
|
||||
|
||||
elif filter_type == "lowshelf":
|
||||
if peak_gain >= 0:
|
||||
norm = 1 / (1 + math.sqrt(2) * K + K * K)
|
||||
self.coefficients['a0'] = (1 + math.sqrt(2*V) * K + V * K * K) * norm
|
||||
self.coefficients['a1'] = 2 * (V * K * K - 1) * norm
|
||||
self.coefficients['a2'] = (1 - math.sqrt(2*V) * K + V * K * K) * norm
|
||||
self.coefficients['b1'] = 2 * (K * K - 1) * norm
|
||||
self.coefficients['b2'] = (1 - math.sqrt(2) * K + K * K) * norm
|
||||
else:
|
||||
norm = 1 / (1 + math.sqrt(2*V) * K + V * K * K)
|
||||
self.coefficients['a0'] = (1 + math.sqrt(2) * K + K * K) * norm
|
||||
self.coefficients['a1'] = 2 * (K * K - 1) * norm
|
||||
self.coefficients['a2'] = (1 - math.sqrt(2) * K + K * K) * norm
|
||||
self.coefficients['b1'] = 2 * (V * K * K - 1) * norm
|
||||
self.coefficients['b2'] = (1 - math.sqrt(2*V) * K + V * K * K) * norm
|
||||
|
||||
elif filter_type == "highshelf":
|
||||
if peak_gain >= 0:
|
||||
norm = 1 / (1 + math.sqrt(2) * K + K * K)
|
||||
self.coefficients['a0'] = (V + math.sqrt(2*V) * K + K * K) * norm
|
||||
self.coefficients['a1'] = 2 * (K * K - V) * norm
|
||||
self.coefficients['a2'] = (V - math.sqrt(2*V) * K + K * K) * norm
|
||||
self.coefficients['b1'] = 2 * (K * K - 1) * norm
|
||||
self.coefficients['b2'] = (1 - math.sqrt(2) * K + K * K) * norm
|
||||
else:
|
||||
norm = 1 / (V + math.sqrt(2*V) * K + K * K)
|
||||
self.coefficients['a0'] = (1 + math.sqrt(2) * K + K * K) * norm
|
||||
self.coefficients['a1'] = 2 * (K * K - 1) * norm
|
||||
self.coefficients['a2'] = (1 - math.sqrt(2) * K + K * K) * norm
|
||||
self.coefficients['b1'] = 2 * (K * K - V) * norm
|
||||
self.coefficients['b2'] = (V - math.sqrt(2*V) * K + K * K) * norm
|
||||
|
||||
else:
|
||||
raise ValueError("不支持的滤波器类型")
|
||||
|
||||
return self.coefficients
|
||||
|
||||
def _check_filter_freq(filter_freq: float, fs: int) -> float:
|
||||
"""检查滤波器频率是否有效"""
|
||||
if filter_freq >= fs / 2:
|
||||
raise ValueError(f"滤波器频率 ({filter_freq} Hz) 必须小于采样率的一半 ({fs/2} Hz)")
|
||||
return filter_freq
|
||||
|
||||
def make_biquad_bypass(fs: int) -> List[float]:
|
||||
"""创建旁路滤波器系数"""
|
||||
return [1.0, 0.0, 0.0, 0.0, 0.0]
|
||||
|
||||
def make_biquad_lowpass(fs: int, filter_freq: float, q_factor: float) -> List[float]:
|
||||
"""创建低通滤波器系数"""
|
||||
filter_freq = _check_filter_freq(filter_freq, fs)
|
||||
K = math.tan(math.pi * filter_freq / fs)
|
||||
norm = 1 / (1 + K / q_factor + K * K)
|
||||
|
||||
b0 = K * K * norm
|
||||
b1 = 2 * b0
|
||||
b2 = b0
|
||||
a1 = 2 * (K * K - 1) * norm
|
||||
a2 = (1 - K / q_factor + K * K) * norm
|
||||
|
||||
return [b0, b1, b2, -a1, -a2]
|
||||
|
||||
def make_biquad_highpass(fs: int, filter_freq: float, q_factor: float) -> List[float]:
|
||||
"""创建高通滤波器系数"""
|
||||
filter_freq = _check_filter_freq(filter_freq, fs)
|
||||
K = math.tan(math.pi * filter_freq / fs)
|
||||
norm = 1 / (1 + K / q_factor + K * K)
|
||||
|
||||
b0 = norm
|
||||
b1 = -2 * b0
|
||||
b2 = b0
|
||||
a1 = 2 * (K * K - 1) * norm
|
||||
a2 = (1 - K / q_factor + K * K) * norm
|
||||
|
||||
return [b0, b1, b2, -a1, -a2]
|
||||
|
||||
def make_biquad_bandpass(fs: int, filter_freq: float, bandwidth: float) -> List[float]:
|
||||
"""创建带通滤波器系数"""
|
||||
filter_freq = _check_filter_freq(filter_freq, fs)
|
||||
w0 = 2.0 * math.pi * filter_freq / fs
|
||||
alpha = math.sin(w0) * math.sinh(math.log(2) / 2 * bandwidth * w0 / math.sin(w0))
|
||||
|
||||
b0 = alpha
|
||||
b1 = 0.0
|
||||
b2 = -alpha
|
||||
a0 = 1.0 + alpha
|
||||
a1 = -2.0 * math.cos(w0)
|
||||
a2 = 1.0 - alpha
|
||||
|
||||
return [b0/a0, b1/a0, b2/a0, -a1/a0, -a2/a0]
|
||||
|
||||
def make_biquad_bandstop(fs: int, filter_freq: float, bandwidth: float) -> List[float]:
|
||||
"""创建带阻滤波器系数 - 使用lib_audio_dsp中biquad.c的算法"""
|
||||
filter_freq = _check_filter_freq(filter_freq, fs)
|
||||
w0 = 2.0 * math.pi * filter_freq / fs
|
||||
sin_w0 = math.sin(w0)
|
||||
alpha = sin_w0 * math.sinh(math.log(2) / 2.0 * bandwidth * w0 / sin_w0)
|
||||
|
||||
b0 = 1.0
|
||||
b1 = -2.0 * math.cos(w0)
|
||||
b2 = 1.0
|
||||
a0 = 1.0 + alpha
|
||||
a1 = b1 # 与lib_audio_dsp一致
|
||||
a2 = 1.0 - alpha
|
||||
|
||||
return [b0/a0, b1/a0, b2/a0, -a1/a0, -a2/a0]
|
||||
|
||||
def make_biquad_notch(fs: int, filter_freq: float, q_factor: float) -> List[float]:
|
||||
"""创建陷波滤波器系数"""
|
||||
filter_freq = _check_filter_freq(filter_freq, fs)
|
||||
K = math.tan(math.pi * filter_freq / fs)
|
||||
norm = 1 / (1 + K / q_factor + K * K)
|
||||
|
||||
b0 = (1 + K * K) * norm
|
||||
b1 = 2 * (K * K - 1) * norm
|
||||
b2 = b0
|
||||
a1 = b1
|
||||
a2 = (1 - K / q_factor + K * K) * norm
|
||||
|
||||
return [b0, b1, b2, -a1, -a2]
|
||||
|
||||
def make_biquad_allpass(fs: int, filter_freq: float, q_factor: float) -> List[float]:
|
||||
"""创建全通滤波器系数"""
|
||||
filter_freq = _check_filter_freq(filter_freq, fs)
|
||||
K = math.tan(math.pi * filter_freq / fs)
|
||||
norm = 1 / (1 + K / q_factor + K * K)
|
||||
|
||||
b0 = (1 - K / q_factor + K * K) * norm
|
||||
b1 = 2 * (K * K - 1) * norm
|
||||
b2 = 1.0
|
||||
a1 = b1
|
||||
a2 = b0
|
||||
|
||||
return [b0, b1, b2, -a1, -a2]
|
||||
|
||||
def make_biquad_peaking(fs: int, filter_freq: float, q_factor: float, boost_db: float) -> List[float]:
|
||||
"""创建峰值滤波器系数"""
|
||||
filter_freq = _check_filter_freq(filter_freq, fs)
|
||||
A = math.sqrt(10 ** (boost_db / 20))
|
||||
w0 = 2.0 * math.pi * filter_freq / fs
|
||||
alpha = math.sin(w0) / (2.0 * q_factor)
|
||||
|
||||
b0 = 1.0 + alpha * A
|
||||
b1 = -2.0 * math.cos(w0)
|
||||
b2 = 1.0 - alpha * A
|
||||
a0 = 1.0 + alpha / A
|
||||
a1 = -2.0 * math.cos(w0)
|
||||
a2 = 1.0 - alpha / A
|
||||
|
||||
return [b0/a0, b1/a0, b2/a0, -a1/a0, -a2/a0]
|
||||
|
||||
def make_biquad_constant_q(fs: int, filter_freq: float, q_factor: float, boost_db: float) -> List[float]:
|
||||
"""创建恒定Q值滤波器系数"""
|
||||
filter_freq = _check_filter_freq(filter_freq, fs)
|
||||
V = 10 ** (boost_db / 20)
|
||||
w0 = 2.0 * math.pi * filter_freq / fs
|
||||
K = math.tan(w0 / 2)
|
||||
|
||||
if boost_db > 0:
|
||||
b0 = 1 + V * K / q_factor + K**2
|
||||
b1 = 2 * (K**2 - 1)
|
||||
b2 = 1 - V * K / q_factor + K**2
|
||||
a0 = 1 + K / q_factor + K**2
|
||||
a1 = 2 * (K**2 - 1)
|
||||
a2 = 1 - K / q_factor + K**2
|
||||
else:
|
||||
V = 1 / V
|
||||
b0 = 1 + K / q_factor + K**2
|
||||
b1 = 2 * (K**2 - 1)
|
||||
b2 = 1 - K / q_factor + K**2
|
||||
a0 = 1 + V * K / q_factor + K**2
|
||||
a1 = 2 * (K**2 - 1)
|
||||
a2 = 1 - V * K / q_factor + K**2
|
||||
|
||||
return [b0/a0, b1/a0, b2/a0, -a1/a0, -a2/a0]
|
||||
|
||||
def make_biquad_lowshelf(fs: int, filter_freq: float, q_factor: float, boost_db: float) -> List[float]:
|
||||
"""创建低架滤波器系数"""
|
||||
filter_freq = _check_filter_freq(filter_freq, fs)
|
||||
A = math.pow(10, boost_db / 40)
|
||||
w0 = 2.0 * math.pi * filter_freq / fs
|
||||
alpha = math.sin(w0) / 2 * math.sqrt((A + 1/A) * (1/q_factor - 1) + 2)
|
||||
|
||||
if boost_db >= 0:
|
||||
b0 = A * ((A+1) + (A-1)*math.cos(w0) + 2*math.sqrt(A)*alpha)
|
||||
b1 = -2*A * ((A-1) + (A+1)*math.cos(w0))
|
||||
b2 = A * ((A+1) + (A-1)*math.cos(w0) - 2*math.sqrt(A)*alpha)
|
||||
a0 = (A+1) - (A-1)*math.cos(w0) + 2*math.sqrt(A)*alpha
|
||||
a1 = 2*((A-1) - (A+1)*math.cos(w0))
|
||||
a2 = (A+1) - (A-1)*math.cos(w0) - 2*math.sqrt(A)*alpha
|
||||
else:
|
||||
b0 = (A+1) - (A-1)*math.cos(w0) + 2*math.sqrt(A)*alpha
|
||||
b1 = 2*((A-1) - (A+1)*math.cos(w0))
|
||||
b2 = (A+1) - (A-1)*math.cos(w0) - 2*math.sqrt(A)*alpha
|
||||
a0 = A*((A+1) + (A-1)*math.cos(w0) + 2*math.sqrt(A)*alpha)
|
||||
a1 = -2*A*((A-1) + (A+1)*math.cos(w0))
|
||||
a2 = A*((A+1) + (A-1)*math.cos(w0) - 2*math.sqrt(A)*alpha)
|
||||
|
||||
return [b0/a0, b1/a0, b2/a0, -a1/a0, -a2/a0]
|
||||
|
||||
def make_biquad_highshelf(fs: int, filter_freq: float, q_factor: float, boost_db: float) -> List[float]:
|
||||
"""创建高架滤波器系数"""
|
||||
filter_freq = _check_filter_freq(filter_freq, fs)
|
||||
A = math.pow(10, boost_db / 40) # 将dB转换为线性增益
|
||||
w0 = 2.0 * math.pi * filter_freq / fs # 归一化角频率
|
||||
alpha = math.sin(w0) / 2 * math.sqrt((A + 1/A) * (1/q_factor - 1) + 2)
|
||||
|
||||
if boost_db >= 0: # 增益提升
|
||||
b0 = A*((A+1) + (A-1)*math.cos(w0) + 2*math.sqrt(A)*alpha)
|
||||
b1 = -2*A*((A-1) + (A+1)*math.cos(w0))
|
||||
b2 = A*((A+1) + (A-1)*math.cos(w0) - 2*math.sqrt(A)*alpha)
|
||||
a0 = (A+1) - (A-1)*math.cos(w0) + 2*math.sqrt(A)*alpha
|
||||
a1 = 2*((A-1) - (A+1)*math.cos(w0))
|
||||
a2 = (A+1) - (A-1)*math.cos(w0) - 2*math.sqrt(A)*alpha
|
||||
else: # 增益衰减
|
||||
b0 = (A+1) - (A-1)*math.cos(w0) + 2*math.sqrt(A)*alpha
|
||||
b1 = 2*((A-1) - (A+1)*math.cos(w0))
|
||||
b2 = (A+1) - (A-1)*math.cos(w0) - 2*math.sqrt(A)*alpha
|
||||
a0 = A*((A+1) + (A-1)*math.cos(w0) + 2*math.sqrt(A)*alpha)
|
||||
a1 = -2*A*((A-1) + (A+1)*math.cos(w0))
|
||||
a2 = A*((A+1) + (A-1)*math.cos(w0) - 2*math.sqrt(A)*alpha)
|
||||
|
||||
return coeffs
|
||||
@@ -0,0 +1,296 @@
|
||||
// Copyright 2021 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XCORE VocalFusion Licence.
|
||||
|
||||
#ifndef __hid_report_descriptor_h__
|
||||
#define __hid_report_descriptor_h__
|
||||
|
||||
#include "xua_hid_report.h"
|
||||
|
||||
#if 0
|
||||
/* Existing static report descriptor kept for reference */
|
||||
#ifdef HID_CONTROLS
|
||||
unsigned char hidReportDescriptor[] =
|
||||
{
|
||||
0x05, 0x0c, /* Usage Page (Consumer Device) */
|
||||
0x09, 0x01, /* Usage (Consumer Control) */
|
||||
0xa1, 0x01, /* Collection (Application) */
|
||||
#ifdef DFU_CONTROL_USB_HID
|
||||
0x85, 0x01, // HID_BUTTON_REPORT_ID // TODO: report ID uses the global definition
|
||||
#endif
|
||||
0x15, 0x00, /* Logical Minimum (0) */
|
||||
0x25, 0x01, /* Logical Maximum (1) */
|
||||
0x09, 0xb0, /* Usage (Play) */
|
||||
0x09, 0xb5, /* Usage (Scan Next Track) */
|
||||
0x09, 0xb6, /* Usage (Scan Previous Track) */
|
||||
0x09, 0xe9, /* Usage (Volume Up) */
|
||||
0x09, 0xea, /* Usage (Volume Down) */
|
||||
0x09, 0xe2, /* Usage (Mute) */
|
||||
0x75, 0x01, /* Report Size (1) */
|
||||
0x95, 0x06, /* Report Count (6) */
|
||||
0x81, 0x02, /* Input (Data, Var, Abs) */
|
||||
0x95, 0x02, /* Report Count (2) */
|
||||
0x81, 0x01, /* Input (Cnst, Ary, Abs) */
|
||||
0xc0 /* End collection */
|
||||
|
||||
#ifdef DFU_CONTROL_USB_HID
|
||||
,0x06, 0x82, 0xff,
|
||||
0x09, 0x01,
|
||||
0xa1, 0x01,
|
||||
0x09, 0x03,
|
||||
0x85, 0x41, // HID_DFU_REPORT_ID // TODO: report ID uses the global definition
|
||||
0x15, 0x00,
|
||||
0x26, 0xff, 0x00,
|
||||
0x75, 0x08,
|
||||
0x95, 0x3f,
|
||||
0x81, 0x02,
|
||||
0x09, 0x04,
|
||||
0x15, 0x00,
|
||||
0x26, 0xff, 0x00,
|
||||
0x75, 0x08,
|
||||
0x95, 0x3f,
|
||||
0x91, 0x02,
|
||||
0xc0
|
||||
#if 0
|
||||
Usage Page (Vendor-Defined 131) 06 82 FF
|
||||
Usage (Vendor-Defined 1) 09 01
|
||||
Collection (Application) A1 01
|
||||
Usage (Vendor-Defined 3) 09 03
|
||||
Report ID (65) 85 41
|
||||
Logical Minimum (0) 15 00
|
||||
Logical Maximum (255) 26 FF 00
|
||||
Report Size (8) 75 08
|
||||
Report Count (63) 95 3F
|
||||
Input (Data,Var,Abs,NWrp,Lin,Pref,NNul,Bit) 81 02
|
||||
Usage (Vendor-Defined 4) 09 04
|
||||
Logical Minimum (0) 15 00
|
||||
Logical Maximum (255) 26 FF 00
|
||||
Report Size (8) 75 08
|
||||
Report Count (63) 95 3F
|
||||
Output (Data,Var,Abs,NWrp,Lin,Pref,NNul,NVol,Bit) 91 02
|
||||
End Collection C0
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Define non-configurable items in the HID Report descriptor.
|
||||
*/
|
||||
static const USB_HID_Short_Item_t hidCollectionApplication = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
|
||||
.data = { 0x01, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidCollectionApplication2 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_COLLECTION),
|
||||
.data = { 0x02, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidCollectionEnd = {
|
||||
.header = HID_REPORT_SET_HEADER(0, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_END_COLLECTION),
|
||||
.data = { 0x00, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidInputConstArray = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
|
||||
.data = { 0x01, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidInputDataVar = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_INPUT),
|
||||
.data = { 0x02, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidInputFeatureVar = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_MAIN, HID_REPORT_ITEM_TAG_FEATURE),
|
||||
.data = { 0x01, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidLogicalMaximum0 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
|
||||
.data = { 0x00, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidLogicalMaximum1 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MAXIMUM),
|
||||
.data = { 0x01, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidLogicalMinimum0 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_LOGICAL_MINIMUM),
|
||||
.data = { 0x00, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidReportCount2 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
|
||||
.data = { 0x00, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidReportCount8 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_COUNT),
|
||||
.data = { 0x08, 0x00 } };
|
||||
static const USB_HID_Short_Item_t hidReportSize1 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_REPORT_SIZE),
|
||||
.data = { 0x01, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidUsageConsumerControl = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.data = { 0x01, 0x00 } };
|
||||
|
||||
static const USB_HID_Short_Item_t hidUsageConsumerControl2 = {
|
||||
.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.data = { 0x02, 0x00 } };
|
||||
|
||||
|
||||
/*
|
||||
* Define the HID Report Descriptor Item, Usage Page, Report ID and length for each HID Report
|
||||
* For internal purposes, a report element with ID of 0 must be included if report IDs are not being used.
|
||||
*/
|
||||
static const USB_HID_Report_Element_t hidReportPageConsumer = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
|
||||
.item.data = { USB_HID_USAGE_PAGE_ID_CONSUMER, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0x1, 2, 0, 0 )
|
||||
};
|
||||
|
||||
static const USB_HID_Report_Element_t hidReportPageVendor = {
|
||||
.item.header = HID_REPORT_SET_HEADER(2, HID_REPORT_ITEM_TYPE_GLOBAL, HID_REPORT_ITEM_TAG_USAGE_PAGE),
|
||||
.item.data = {0x83, 0xff },
|
||||
.location = HID_REPORT_SET_LOC(0x2, 2, 0, 0 )
|
||||
};
|
||||
|
||||
|
||||
static const USB_HID_Short_Item_t hidUsagePageConsumer = { .header = 0x05, .data = { 0x0C, 0x00 }};
|
||||
|
||||
static const USB_HID_Short_Item_t hidUsagePageVendor = { .header = 0x06, .data = { 0x82, 0xff }};
|
||||
|
||||
static const USB_HID_Short_Item_t hidUsageConsumerVendor = { .header = 0x09, .data = { 0x03, 0x00 }};
|
||||
|
||||
static const USB_HID_Short_Item_t hidPassReportId = { .header = 0x85, .data = { 0x1, 0x00 }};
|
||||
static const USB_HID_Short_Item_t hidButtonReportId = { .header = 0x85, .data = { 0x2, 0x00 }};
|
||||
|
||||
static const USB_HID_Short_Item_t hidLogicalMaximum2 = { .header = 0x26, .data = { 0xFF, 0x00 }};
|
||||
|
||||
static const USB_HID_Short_Item_t hidReportSize = { .header = 0x75, .data = { 0x08, 0x00 }};
|
||||
#if DEBUG_MEMORY_LOG_ENABLED
|
||||
static const USB_HID_Short_Item_t hidPassReportCount = { .header = 0x95, .data = { 0x3F, 0x00 }};
|
||||
static const USB_HID_Short_Item_t hidPassReportCount2 = { .header = 0x95, .data = { 0x3F, 0x00 }};
|
||||
static const USB_HID_Short_Item_t hidPassReportCount3 = { .header = 0x95, .data = { 0x3f, 0x00 }};
|
||||
#else
|
||||
static const USB_HID_Short_Item_t hidPassReportCount = { .header = 0x95, .data = { 0x3f, 0x00 }};
|
||||
static const USB_HID_Short_Item_t hidPassReportCount2 = { .header = 0x95, .data = { 0x3f, 0x00 }};
|
||||
static const USB_HID_Short_Item_t hidPassReportCount3 = { .header = 0x95, .data = { 0x3f, 0x00 }};
|
||||
#endif
|
||||
static const USB_HID_Short_Item_t hidButtonReportCount = { .header = 0x95, .data = { 0x04, 0x00 }};
|
||||
static const USB_HID_Short_Item_t hidUsageVendor = { .header = 0x09, .data = { 0x04, 0x00 }};
|
||||
static const USB_HID_Short_Item_t hidUsageVendor2 = { .header = 0x09, .data = { 0x05, 0x00 }};
|
||||
static const USB_HID_Short_Item_t hidOutputDataVar = { .header = 0x91, .data = { 0x02, 0x00 }};
|
||||
|
||||
/*
|
||||
* Define configurable items in the HID Report descriptor.
|
||||
*/
|
||||
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit7 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xE2, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 5)
|
||||
}; // Mute
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit6 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xB4, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 5)
|
||||
}; // rewind
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit5 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xB3, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 5)
|
||||
}; // forward
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit4 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xB6, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 2)
|
||||
}; // Scan Prev
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit3 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xB5, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 1)
|
||||
}; // Scan Next
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit2 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xCD, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 0)
|
||||
}; // Play
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit1 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xEA, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 4)
|
||||
}; // Vol-
|
||||
static USB_HID_Report_Element_t hidUsageByte0Bit0 = {
|
||||
.item.header = HID_REPORT_SET_HEADER(1, HID_REPORT_ITEM_TYPE_LOCAL, HID_REPORT_ITEM_TAG_USAGE),
|
||||
.item.data = { 0xE9, 0x00 },
|
||||
.location = HID_REPORT_SET_LOC(0, 0, 0, 3)
|
||||
}; // Vol+
|
||||
|
||||
/*
|
||||
* List the configurable elements in the HID Report descriptor.
|
||||
*/
|
||||
static USB_HID_Report_Element_t* const hidConfigurableElements[] = {
|
||||
&hidUsageByte0Bit0,
|
||||
&hidUsageByte0Bit1,
|
||||
&hidUsageByte0Bit2,
|
||||
&hidUsageByte0Bit3,
|
||||
&hidUsageByte0Bit4,
|
||||
&hidUsageByte0Bit5,
|
||||
&hidUsageByte0Bit6,
|
||||
&hidUsageByte0Bit7
|
||||
};
|
||||
|
||||
/*
|
||||
* List HID Reports, one per Report ID. This should be a usage page item with the relevant
|
||||
* If not using report IDs - still have one with report ID 0
|
||||
*/
|
||||
static const USB_HID_Report_Element_t* const hidReports[] = {
|
||||
&hidReportPageVendor,
|
||||
&hidReportPageConsumer
|
||||
};
|
||||
|
||||
/*
|
||||
* List all items in the HID Report descriptor.
|
||||
*/
|
||||
static const USB_HID_Short_Item_t* const hidReportDescriptorItems[] = {
|
||||
&(hidReportPageVendor.item),
|
||||
&hidUsageConsumerControl,
|
||||
&hidCollectionApplication,
|
||||
&hidUsageConsumerVendor,
|
||||
&hidPassReportId,
|
||||
&hidLogicalMinimum0,
|
||||
&hidLogicalMaximum2,
|
||||
&hidReportSize,
|
||||
&hidPassReportCount2,
|
||||
&hidInputDataVar,
|
||||
&hidUsageVendor,
|
||||
&hidLogicalMinimum0,
|
||||
&hidLogicalMaximum2,
|
||||
&hidReportSize,
|
||||
&hidPassReportCount,
|
||||
&hidOutputDataVar,
|
||||
&hidUsageVendor2,
|
||||
&hidReportSize,
|
||||
&hidPassReportCount3,
|
||||
&hidInputFeatureVar,
|
||||
&hidCollectionEnd,
|
||||
&(hidReportPageConsumer.item),
|
||||
&hidUsageConsumerControl,
|
||||
&hidCollectionApplication,
|
||||
&hidButtonReportId,
|
||||
&hidLogicalMinimum0,
|
||||
&hidLogicalMaximum1,
|
||||
&(hidUsageByte0Bit0.item),
|
||||
&(hidUsageByte0Bit1.item),
|
||||
&(hidUsageByte0Bit2.item),
|
||||
&(hidUsageByte0Bit3.item),
|
||||
&(hidUsageByte0Bit4.item),
|
||||
&(hidUsageByte0Bit5.item),
|
||||
&(hidUsageByte0Bit6.item),
|
||||
&(hidUsageByte0Bit7.item),
|
||||
&hidReportSize1,
|
||||
&hidReportCount8,
|
||||
&hidInputDataVar,
|
||||
&hidReportCount2,
|
||||
&hidInputConstArray,
|
||||
&hidCollectionEnd,
|
||||
};
|
||||
|
||||
/*
|
||||
* Define the number of HID Reports
|
||||
* Due to XC not supporting designated initializers, this constant has a hard-coded value.
|
||||
* It must equal ( sizeof hidReports / sizeof ( USB_HID_Report_Element_t* ))
|
||||
*/
|
||||
#define HID_REPORT_COUNT ( 2 )
|
||||
|
||||
#endif // __hid_report_descriptor_h__
|
||||
@@ -0,0 +1,153 @@
|
||||
#define DEBUG_PRINT_ENABLE 1
|
||||
#include <xs1.h>
|
||||
#include <platform.h>
|
||||
#include "xua_conf.h"
|
||||
|
||||
#include "user_hid.h"
|
||||
#include "xua_hid_report.h"
|
||||
|
||||
#include "xc_ptr.h"
|
||||
|
||||
#include "xud.h"
|
||||
#include "hid.h"
|
||||
#include "debug_print.h"
|
||||
|
||||
#if HID_CONTROLS > 0
|
||||
|
||||
#ifdef XSCOPE
|
||||
#include "print.h"
|
||||
#endif
|
||||
|
||||
#ifdef DFU_CONTROL_USB_HID
|
||||
#include <xccompat.h>
|
||||
|
||||
#define HID_DFU_REPORT_ID 0x41
|
||||
#endif
|
||||
|
||||
#define P_GPI_BUTA_SHIFT 0x00
|
||||
#define P_GPI_BUTA_MASK (1<<P_GPI_BUTA_SHIFT)
|
||||
#define P_GPI_BUTB_SHIFT 0x01
|
||||
#define P_GPI_BUTB_MASK (1<<P_GPI_BUTB_SHIFT)
|
||||
#define P_GPI_BUTC_SHIFT 0x02
|
||||
#define P_GPI_BUTC_MASK (1<<P_GPI_BUTC_SHIFT)
|
||||
#define P_GPI_SW1_SHIFT 0x03
|
||||
#define P_GPI_SW1_MASK (1<<P_GPI_SW1_SHIFT)
|
||||
|
||||
/* Write HID Report Data into hidData array
|
||||
*
|
||||
* Bits are as follows:
|
||||
* 0: Play/Pause
|
||||
* 1: Scan Next Track
|
||||
* 2: Scan Prev Track
|
||||
* 3: Volume Up
|
||||
* 4: Volume Down
|
||||
* 5: Mute
|
||||
*/
|
||||
|
||||
unsigned multicontrol_count = 0;
|
||||
unsigned wait_counter =0;
|
||||
unsigned long get_reference_time();
|
||||
|
||||
#define THRESH 1
|
||||
#define MULTIPRESS_WAIT 25
|
||||
|
||||
#define HID_CONTROL_NEXT 0x02
|
||||
#define HID_CONTROL_PLAYPAUSE 0x01
|
||||
#define HID_CONTROL_PREV 0x04
|
||||
#define HID_CONTROL VOLUP 0x08
|
||||
#define HID_CONTROL_VOLDN 0x10
|
||||
#define HID_CONTROL_MUTE 0x20
|
||||
|
||||
typedef enum
|
||||
{
|
||||
STATE_IDLE = 0x00,
|
||||
STATE_PLAY = 0x01,
|
||||
STATE_NEXTPREV = 0x02,
|
||||
}t_controlState;
|
||||
|
||||
t_controlState state;
|
||||
|
||||
unsigned lastA;
|
||||
|
||||
unsigned g_ButtonVal = 0;
|
||||
unsigned char g_hid_pass_data0;
|
||||
unsigned char g_hid_pass_data1;
|
||||
unsigned char g_hid_pass_data2;
|
||||
unsigned char g_hid_pass_data3;
|
||||
unsigned char g_hid_pass_data4;
|
||||
unsigned char g_hid_pass_data5;
|
||||
unsigned char g_hid_pass_data6;
|
||||
unsigned char g_hid_pass_data7;
|
||||
|
||||
void UserReadHIDButtons(unsigned char hidData[])
|
||||
{
|
||||
unsigned tmp;
|
||||
GET_SHARED_GLOBAL(tmp, g_ButtonVal);
|
||||
hidData[0] = tmp;
|
||||
}
|
||||
|
||||
void UserReadHIDPass(unsigned char hidPassData[])
|
||||
{
|
||||
int i = 0;
|
||||
GET_SHARED_GLOBAL(hidPassData[i++], g_hid_pass_data0);
|
||||
GET_SHARED_GLOBAL(hidPassData[i++], g_hid_pass_data1);
|
||||
GET_SHARED_GLOBAL(hidPassData[i++], g_hid_pass_data2);
|
||||
GET_SHARED_GLOBAL(hidPassData[i++], g_hid_pass_data3);
|
||||
GET_SHARED_GLOBAL(hidPassData[i++], g_hid_pass_data4);
|
||||
GET_SHARED_GLOBAL(hidPassData[i++], g_hid_pass_data5);
|
||||
GET_SHARED_GLOBAL(hidPassData[i++], g_hid_pass_data6);
|
||||
GET_SHARED_GLOBAL(hidPassData[i++], g_hid_pass_data7);
|
||||
|
||||
SET_SHARED_GLOBAL(g_hid_pass_data0, 0);
|
||||
SET_SHARED_GLOBAL(g_hid_pass_data1, 0);
|
||||
SET_SHARED_GLOBAL(g_hid_pass_data2, 0);
|
||||
SET_SHARED_GLOBAL(g_hid_pass_data3, 0);
|
||||
SET_SHARED_GLOBAL(g_hid_pass_data4, 0);
|
||||
SET_SHARED_GLOBAL(g_hid_pass_data5, 0);
|
||||
SET_SHARED_GLOBAL(g_hid_pass_data6, 0);
|
||||
SET_SHARED_GLOBAL(g_hid_pass_data7, 0);
|
||||
}
|
||||
|
||||
#if DEBUG_MEMORY_LOG_ENABLED
|
||||
|
||||
extern unsigned int debug_memory_log_buffer_index;
|
||||
#define DEBUG_MEMORY_LOG_BUFFER_SIZE 2048
|
||||
extern unsigned char debug_memory_log_buffer[DEBUG_MEMORY_LOG_BUFFER_SIZE];
|
||||
unsigned int log_index = 0;
|
||||
|
||||
void UserReadHIDLog(unsigned char hidLogData[])
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
unsigned char * unsafe logPtr = debug_memory_log_buffer;
|
||||
unsigned size = (debug_memory_log_buffer_index - log_index >= 64) ? 64 : (debug_memory_log_buffer_index - log_index);
|
||||
if (size > 0)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
hidLogData[i] = logPtr[log_index + i];
|
||||
}
|
||||
|
||||
log_index += size;
|
||||
|
||||
if (log_index >= debug_memory_log_buffer_index)
|
||||
{
|
||||
log_index = 0;
|
||||
SET_SHARED_GLOBAL(debug_memory_log_buffer_index, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < 64; i++)
|
||||
{
|
||||
hidLogData[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,102 @@
|
||||
#ifndef _HOST_OS_DETECT_H_
|
||||
#define _HOST_OS_DETECT_H_
|
||||
|
||||
#include "xua.h"
|
||||
#include "xc_ptr.h"
|
||||
#include "xassert.h"
|
||||
#if XUA_USB_EN
|
||||
#ifndef WINDOWS_OS_DESCRIPTOR_SUPPORT
|
||||
#define WINDOWS_OS_DESCRIPTOR_SUPPORT
|
||||
#endif
|
||||
#define EP0_MAX_REQUEST_SIZE 2048
|
||||
#include "xud.h"
|
||||
#include "vendorrequests.h"
|
||||
|
||||
unsigned g_host_os = 0; // 1 -> Windows, 0 -> Others
|
||||
|
||||
|
||||
int VendorAudioRequests(XUD_ep ep0_out, XUD_ep ep0_in, unsigned char bRequest, unsigned char cs, unsigned char cn,
|
||||
unsigned short unitId, unsigned char direction, NULLABLE_RESOURCE(chanend, c_aud_ctl),
|
||||
NULLABLE_RESOURCE(chanend, c_mix_ctl),
|
||||
NULLABLE_RESOURCE(chanend, c_clk_ctL))
|
||||
{
|
||||
|
||||
return XUD_RES_ERR;
|
||||
}
|
||||
enum { OS_WIN = 1, OS_OTHERS = 2 };
|
||||
#if 1
|
||||
int VendorRequests(XUD_ep ep0_out, XUD_ep ep0_in, REFERENCE_PARAM(USB_SetupPacket_t, sp) VENDOR_REQUESTS_PARAMS_DEC_)
|
||||
{
|
||||
XUD_Result_t result = XUD_RES_ERR;
|
||||
|
||||
unsigned char request_data[EP0_MAX_REQUEST_SIZE];
|
||||
unsigned len;
|
||||
int a = 0;
|
||||
unsigned k = 5;
|
||||
//SET_SHARED_GLOBAL(g_host_os, k);
|
||||
switch ((sp->bmRequestType.Direction << 7) | (sp->bmRequestType.Type << 5) | (sp->bmRequestType.Recipient)) {
|
||||
case USB_BMREQ_H2D_VENDOR_DEV:
|
||||
result = XUD_GetBuffer(ep0_out, request_data, len);
|
||||
if (result == XUD_RES_OKAY) {
|
||||
if (a/*control_process_usb_set_request(sp.wIndex, sp.wValue, sp.wLength, request_data, i_control) == CONTROL_SUCCESS*/) {
|
||||
/* zero length data to indicate success
|
||||
* on control error, go to standard requests, which will issue STALL
|
||||
*/
|
||||
result = XUD_DoSetRequestStatus(ep0_in);
|
||||
} else {
|
||||
result = XUD_RES_ERR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case USB_BMREQ_D2H_VENDOR_DEV:
|
||||
/* application retrieval latency inside the control library call
|
||||
* XUD task defers further calls by NAKing USB transactions
|
||||
*/
|
||||
// if (a/*control_process_usb_get_request(sp.wIndex, sp.wValue, sp.wLength, request_data, i_control) == CONTROL_SUCCESS*/) {
|
||||
// len = sp->wLength;
|
||||
// result = XUD_DoGetRequest(ep0_out, ep0_in, request_data, len, len);
|
||||
// /* on control error, go to standard requests, which will issue STALL */
|
||||
// }
|
||||
#ifdef WINDOWS_OS_DESCRIPTOR_SUPPORT
|
||||
// else
|
||||
if(sp->bRequest == 0x01) // GET_MS_DESCRIPTOR, same as the OS_STR_DESC last byte
|
||||
{
|
||||
// dwLength, 4bytes: 16 bytes
|
||||
request_data[0] = 0x10; request_data[1] = 0x00; request_data[2] = 0x00; request_data[3] = 0x00;
|
||||
// bcdVersion, 2bytes: For version 1.00, bcdVersion is set to 0x0100.
|
||||
request_data[4] = 0x00; request_data[5] = 0x01;
|
||||
// wIndex, 2bytes: 0x04 for extended compat ID descriptors
|
||||
request_data[6] = 0x04; request_data[7] = 0x00;
|
||||
// bCount, 1byte: 0
|
||||
request_data[8] = 0x00;
|
||||
// RESERVED, 7bytes: all 0
|
||||
request_data[9] = 0x00; request_data[10] = 0x00; request_data[11] = 0x00;
|
||||
request_data[12] = 0x00; request_data[13] = 0x00; request_data[14] = 0x00; request_data[15] = 0x00;
|
||||
|
||||
result = XUD_DoGetRequest(ep0_out, ep0_in, request_data, 16, sp->wLength);
|
||||
//xassert(busSpeed == XUD_SPEED_HS);
|
||||
k = OS_WIN;
|
||||
SET_SHARED_GLOBAL(g_host_os, k);
|
||||
}
|
||||
|
||||
else {
|
||||
//xassert(busSpeed == XUD_SPEED_FS);
|
||||
k = OS_OTHERS;
|
||||
SET_SHARED_GLOBAL(g_host_os, k);
|
||||
result = XUD_RES_ERR;
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
void VendorRequests_Init(VENDOR_REQUESTS_PARAMS_DEC)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#endif /* XUA_USB_EN */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,21 @@
|
||||
#include <platform.h>
|
||||
|
||||
/* This is provided as simple example but disabled due to the port clash with audiostream.xc */
|
||||
|
||||
#if 0
|
||||
on tile[0]: out port p_leds = XS1_PORT_4F;
|
||||
|
||||
void UserHostActive(int active)
|
||||
{
|
||||
if(active)
|
||||
{
|
||||
/* Turn all LEDs on */
|
||||
p_leds <: 0xF;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Turn all LEDs off */
|
||||
p_leds <: 0x0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,203 @@
|
||||
/**
|
||||
* @file htr3236.h
|
||||
* @brief HTR3236 36-Channel LED PWM Driver Driver for XMOS Platform
|
||||
* @version 1.1
|
||||
*/
|
||||
|
||||
#ifndef HTR3236_H
|
||||
#define HTR3236_H
|
||||
|
||||
#include <xccompat.h>
|
||||
#include <stdint.h>
|
||||
#include <i2c.h>
|
||||
|
||||
/*=========================================================================
|
||||
I2C 寄存器地址定义
|
||||
-----------------------------------------------------------------------*/
|
||||
#define HTR3236_REG_SHUTDOWN 0x00 // 软件关断寄存器
|
||||
#define HTR3236_REG_PWM_START 0x01 // PWM 寄存器起始地址 (OUT1)
|
||||
#define HTR3236_REG_PWM_END 0x24 // PWM 寄存器结束地址 (OUT36)
|
||||
#define HTR3236_REG_PWM_UPDATE 0x25 // PWM 更新寄存器
|
||||
#define HTR3236_REG_LED_CTRL_START 0x26 // LED 控制寄存器起始地址 (OUT1)
|
||||
#define HTR3236_REG_LED_CTRL_END 0x49 // LED 控制寄存器结束地址 (OUT36)
|
||||
#define HTR3236_REG_GLOBAL_CTRL 0x4A // 全局控制寄存器
|
||||
#define HTR3236_REG_FREQ_SET 0x4B // 频率设置寄存器
|
||||
#define HTR3236_REG_RESET 0x4F // 复位寄存器
|
||||
|
||||
/*=========================================================================
|
||||
寄存器位定义
|
||||
-----------------------------------------------------------------------*/
|
||||
// 关断寄存器 (00h)
|
||||
#define HTR3236_SHUTDOWN_MASK 0x01
|
||||
#define HTR3236_SHUTDOWN_SOFT 0x00
|
||||
#define HTR3236_NORMAL_OP 0x01
|
||||
|
||||
// LED 控制寄存器位 (26h~49h)
|
||||
#define HTR3236_LED_OUT_MASK 0x01
|
||||
#define HTR3236_LED_CURRENT_SHIFT 1
|
||||
#define HTR3236_LED_CURRENT_MASK (0x03 << 1)
|
||||
|
||||
// 全局控制寄存器 (4Ah)
|
||||
#define HTR3236_GLOBAL_EN_MASK 0x01
|
||||
|
||||
// 频率设置寄存器 (4Bh)
|
||||
// #define HTR3236_FREQ_3KHZ 0x00
|
||||
// #define HTR3236_FREQ_22KHZ 0x01
|
||||
// #define HTR3236_FREQ_MASK 0x01
|
||||
|
||||
/*=========================================================================
|
||||
数据类型定义
|
||||
-----------------------------------------------------------------------*/
|
||||
typedef enum {
|
||||
HTR3236_CURRENT_FULL = 0, // IMAX
|
||||
HTR3236_CURRENT_HALF = 1, // IMAX/2
|
||||
HTR3236_CURRENT_THIRD = 2, // IMAX/3
|
||||
HTR3236_CURRENT_QUARTER = 3 // IMAX/4
|
||||
} htr3236_current_t;
|
||||
|
||||
typedef enum {
|
||||
HTR3236_FREQ_3KHZ = 0,
|
||||
HTR3236_FREQ_22KHZ = 1
|
||||
} htr3236_freq_t;
|
||||
|
||||
typedef enum {
|
||||
HTR3236_ADDR_GND = 0x3C, // AD = GND: 8位地址 0x78
|
||||
HTR3236_ADDR_SCL = 0x3D, // AD = SCL: 8位地址 0x7A
|
||||
HTR3236_ADDR_SDA = 0x3E, // AD = SDA: 8位地址 0x7C
|
||||
HTR3236_ADDR_VCC = 0x3F // AD = VCC: 8位地址 0x7E
|
||||
} htr3236_addr_t;
|
||||
|
||||
/**
|
||||
* @brief HTR3236 设备结构体
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t i2c_addr; // I2C 设备地址
|
||||
} htr3236_t;
|
||||
|
||||
/*=========================================================================
|
||||
API 函数声明
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief 初始化 HTR3236 设备
|
||||
* @param dev 设备结构体指针
|
||||
* @param i2c I2C 主控接口
|
||||
* @param addr I2C 设备地址
|
||||
* @param sdb_port SDB 控制端口
|
||||
* @param sdb_pin SDB 引脚号
|
||||
*/
|
||||
void htr3236_init(htr3236_t *dev, uint8_t addr);
|
||||
|
||||
/**
|
||||
* @brief 硬件使能 (SDB 拉高)
|
||||
* @param dev 设备结构体指针
|
||||
*/
|
||||
void htr3236_hw_enable(htr3236_t *dev);
|
||||
|
||||
/**
|
||||
* @brief 硬件关断 (SDB 拉低)
|
||||
* @param dev 设备结构体指针
|
||||
*/
|
||||
void htr3236_hw_disable(htr3236_t *dev);
|
||||
|
||||
/**
|
||||
* @brief 软件唤醒 (正常模式)
|
||||
* @param dev 设备结构体指针
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int htr3236_software_wake(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c));
|
||||
|
||||
/**
|
||||
* @brief 软件关断
|
||||
* @param dev 设备结构体指针
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int htr3236_software_shutdown(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c));
|
||||
|
||||
/**
|
||||
* @brief 软件复位所有寄存器
|
||||
* @param dev 设备结构体指针
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int htr3236_software_reset(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c));
|
||||
|
||||
/**
|
||||
* @brief 设置单路 PWM 亮度
|
||||
* @param dev 设备结构体指针
|
||||
* @param channel 通道号 (1-36)
|
||||
* @param brightness 亮度值 (0-255)
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int htr3236_set_pwm(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t channel, uint8_t brightness);
|
||||
|
||||
/**
|
||||
* @brief 批量设置多路 PWM 亮度 (使用自动地址递增)
|
||||
* @param dev 设备结构体指针
|
||||
* @param start_ch 起始通道号 (1-36)
|
||||
* @param values 亮度值数组
|
||||
* @param len 通道数量
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief 设置单路 LED 电流档位和使能状态
|
||||
* @param dev 设备结构体指针
|
||||
* @param channel 通道号 (1-36)
|
||||
* @param current 电流档位
|
||||
* @param enable LED 使能 (1:开启, 0:关闭)
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int htr3236_set_led_config(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t channel,
|
||||
htr3236_current_t current, uint8_t enable);
|
||||
|
||||
/**
|
||||
* @brief 批量设置多路 LED 配置
|
||||
* @param dev 设备结构体指针
|
||||
* @param start_ch 起始通道号 (1-36)
|
||||
* @param configs 配置数据数组 (每个字节: bit0=使能, bit2-1=电流档位)
|
||||
* @param len 通道数量
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
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);
|
||||
|
||||
/**
|
||||
* @brief 更新 PWM 和 LED 配置 (写入 25h 寄存器)
|
||||
* @param dev 设备结构体指针
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int htr3236_update(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c));
|
||||
|
||||
/**
|
||||
* @brief 全局 LED 使能控制
|
||||
* @param dev 设备结构体指针
|
||||
* @param enable 1:关闭所有LED, 0:正常模式
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int htr3236_global_enable(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), uint8_t enable);
|
||||
|
||||
/**
|
||||
* @brief 设置 PWM 频率
|
||||
* @param dev 设备结构体指针
|
||||
* @param freq 频率 (0:3kHz, 1:22kHz)
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int htr3236_set_frequency(htr3236_t *dev, CLIENT_INTERFACE(i2c_master_if, i2c), htr3236_freq_t freq);
|
||||
|
||||
/**
|
||||
* @brief Gamma 校正查找表 (32级)
|
||||
* @param index Gamma 索引 (0-31)
|
||||
* @return PWM 值 (0-255)
|
||||
*/
|
||||
uint8_t htr3236_gamma_32(uint8_t index);
|
||||
|
||||
/**
|
||||
* @brief Gamma 校正查找表 (64级)
|
||||
* @param index Gamma 索引 (0-63)
|
||||
* @return PWM 值 (0-255)
|
||||
*/
|
||||
uint8_t htr3236_gamma_64(uint8_t index);
|
||||
|
||||
#endif /* HTR3236_H */
|
||||
@@ -0,0 +1,252 @@
|
||||
/**
|
||||
* @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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
// Copyright 2011-2023 XMOS LIMITED.
|
||||
// This Software is subject to the terms of the XMOS Public Licence: Version 1.
|
||||
#ifndef __KEYS_H__
|
||||
#define __KEYS_H__
|
||||
|
||||
|
||||
#define KEY_MIC_VOL_DN 0x08
|
||||
#define KEY_MUTE 0x10
|
||||
#define KEY_MIC_VOL_UP 0x20
|
||||
#define KEY_PLAY_VOL_DN 0x40
|
||||
#define KEY_PLAY_VOL_UP 0x80
|
||||
#define KEY_BITS (KEY_MIC_VOL_DN | KEY_MUTE | KEY_MIC_VOL_UP | KEY_PLAY_VOL_DN | KEY_PLAY_VOL_UP)
|
||||
|
||||
#define MUTED_MIC 0x5A
|
||||
#define UNMUTED_MIC 0xA5
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,265 @@
|
||||
/**
|
||||
* @file led_control.c
|
||||
* @brief LED控制API实现 (基于HTR3236)
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
#include "led_control.h"
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <timer.h>
|
||||
|
||||
/*=========================================================================
|
||||
内部函数
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief 检查LED ID是否有效
|
||||
*/
|
||||
static int is_valid_led(led_id_t led)
|
||||
{
|
||||
return (led >= 1 && led <= 36 && led != 36); // OUT36未使用
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 获取LED组起始和结束索引
|
||||
*/
|
||||
static void get_group_range(led_group_t group, uint8_t *start, uint8_t *end)
|
||||
{
|
||||
switch (group) {
|
||||
case LED_GROUP_L_SERIES:
|
||||
*start = LED_L1;
|
||||
*end = LED_L15;
|
||||
break;
|
||||
case LED_GROUP_D_SERIES:
|
||||
*start = LED_D1;
|
||||
*end = LED_D15;
|
||||
break;
|
||||
// case LED_GROUP_FUNCTION:
|
||||
// *start = LED_ANC;
|
||||
// *end = LED_GAME_MODE;
|
||||
// break;
|
||||
case LED_GROUP_ALL:
|
||||
default:
|
||||
*start = 1;
|
||||
*end = 35; // 排除OUT36
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*=========================================================================
|
||||
LED物理映射表
|
||||
-----------------------------------------------------------------------*/
|
||||
// 根据测试结果:LED_L1-L15的实际OUT口
|
||||
const uint8_t led_l_physical_map[15] = {
|
||||
15, // LED_L1 -> OUT15
|
||||
14, // LED_L2 -> OUT14
|
||||
13, // LED_L3 -> OUT13
|
||||
11, // LED_L4 -> OUT11
|
||||
10, // LED_L5 -> OUT10
|
||||
9, // LED_L6 -> OUT9
|
||||
8, // LED_L7 -> OUT8
|
||||
7, // LED_L8 -> OUT7
|
||||
6, // LED_L9 -> OUT6
|
||||
5, // LED_L10 -> OUT5
|
||||
4, // LED_L11 -> OUT4
|
||||
12, // LED_L12 -> OUT12 *
|
||||
18, // LED_L13 -> OUT18 *
|
||||
17, // LED_L14 -> OUT17
|
||||
16, // LED_L15 -> OUT16
|
||||
};
|
||||
// 根据测试结果:LED_D1-D15的实际OUT口
|
||||
const uint8_t led_d_physical_map[15] = {
|
||||
21, // LED_D1 -> OUT21
|
||||
20, // LED_D2 -> OUT20
|
||||
19, // LED_D3 -> OUT19
|
||||
26, // LED_D4 -> OUT26 *
|
||||
33, // LED_D5 -> OUT33 *
|
||||
32, // LED_D6 -> OUT32
|
||||
31, // LED_D7 -> OUT31
|
||||
30, // LED_D8 -> OUT30
|
||||
29, // LED_D9 -> OUT29
|
||||
28, // LED_D10 -> OUT28
|
||||
27, // LED_D11 -> OUT27
|
||||
25, // LED_D12 -> OUT25
|
||||
24, // LED_D13 -> OUT24
|
||||
23, // LED_D14 -> OUT23
|
||||
22, // LED_D15 -> OUT22
|
||||
};
|
||||
|
||||
const uint8_t mic_gain_to_led[39] = {
|
||||
0, // [-1] 增益-1: 0个LED,这个设计未启用
|
||||
0, // [0] 增益0: 0个LED
|
||||
0, // [1] 增益1: 0个LED
|
||||
0, // [2] 增益2: 0个LED
|
||||
1, // [3] 增益3: 1个LED
|
||||
1, // [4] 增益4: 1个LED
|
||||
1, // [5] 增益5: 1个LED
|
||||
2, // [6] 增益6: 2个LED
|
||||
2, // [7] 增益7: 2个LED
|
||||
2, // [8] 增益8: 2个LED
|
||||
3, // [9] 增益9: 3个LED
|
||||
3, // [10] 增益10: 3个LED
|
||||
3, // [11] 增益11: 3个LED
|
||||
4, // [12] 增益12: 4个LED
|
||||
4, // [13] 增益13: 4个LED
|
||||
4, // [14] 增益14: 4个LED
|
||||
5, // [15] 增益15: 5个LED
|
||||
5, // [16] 增益16: 5个LED
|
||||
6, // [17] 增益17: 6个LED
|
||||
6, // [18] 增益18: 6个LED
|
||||
7, // [19] 增益19: 7个LED
|
||||
7, // [20] 增益20: 7个LED
|
||||
8, // [21] 增益21: 8个LED
|
||||
8, // [22] 增益22: 8个LED
|
||||
9, // [23] 增益23: 9个LED
|
||||
9, // [24] 增益24: 9个LED
|
||||
10, // [25] 增益25: 10个LED
|
||||
10, // [26] 增益26: 10个LED
|
||||
11, // [27] 增益27: 11个LED
|
||||
11, // [28] 增益28: 11个LED
|
||||
12, // [29] 增益29: 12个LED
|
||||
12, // [30] 增益30: 12个LED
|
||||
13, // [31] 增益31: 13个LED
|
||||
13, // [32] 增益32: 13个LED
|
||||
14, // [33] 增益33: 14个LED
|
||||
14, // [34] 增益34: 14个LED
|
||||
15, // [35] 增益35: 15个LED
|
||||
15, // [36] 增益36: 15个LED
|
||||
15 // [37] 增益36+1.5 digitial gain: 15个LED
|
||||
};
|
||||
|
||||
/*=========================================================================
|
||||
内部函数 - 获取实际OUT口
|
||||
-----------------------------------------------------------------------*/
|
||||
static uint8_t get_physical_out(led_id_t led)
|
||||
{
|
||||
// 如果是L系列LED
|
||||
if (led >= LED_L1 && led <= LED_L15) {
|
||||
uint8_t index = led - LED_L1;
|
||||
return led_l_physical_map[index];
|
||||
}
|
||||
else if (led >= LED_D1 && led <= LED_D15) {
|
||||
uint8_t index = led - LED_D1;
|
||||
return led_d_physical_map[index];
|
||||
}
|
||||
|
||||
// 其他LED直接返回原值
|
||||
return (uint8_t)led;
|
||||
}
|
||||
|
||||
/*=========================================================================
|
||||
基础控制API实现
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
void led_control_init(led_control_t *ctx,
|
||||
htr3236_t *dev,
|
||||
CLIENT_INTERFACE(i2c_master_if,i2c))
|
||||
{
|
||||
ctx->htr3236_dev = dev;
|
||||
ctx->i2c = i2c;
|
||||
|
||||
// 初始化亮度缓存
|
||||
memset(ctx->brightness, 0, sizeof(ctx->brightness));
|
||||
|
||||
// 配置所有LED通道的电流 (使用IMAX/2)
|
||||
for (int led = 1; led <= 35; led++) { // 跳过OUT36
|
||||
htr3236_set_led_config(ctx->htr3236_dev, ctx->i2c,
|
||||
led, HTR3236_CURRENT_HALF, 1);
|
||||
}
|
||||
|
||||
// 初始关闭所有LED
|
||||
for (int led = 1; led <= 35; led++) {
|
||||
htr3236_set_pwm(ctx->htr3236_dev, ctx->i2c, led, 0);
|
||||
}
|
||||
|
||||
htr3236_update(ctx->htr3236_dev, ctx->i2c);
|
||||
}
|
||||
|
||||
int led_set_brightness(led_control_t *ctx,
|
||||
led_id_t led,
|
||||
uint8_t brightness)
|
||||
{
|
||||
if (!is_valid_led(led)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
ctx->brightness[led - 1] = brightness;
|
||||
return htr3236_set_pwm(ctx->htr3236_dev, ctx->i2c, led, brightness);
|
||||
}
|
||||
|
||||
int led_on(led_control_t *ctx, led_id_t led)
|
||||
{
|
||||
return led_set_brightness(ctx, led, 1/*255*/);
|
||||
}
|
||||
|
||||
int led_off(led_control_t *ctx, led_id_t led)
|
||||
{
|
||||
return led_set_brightness(ctx, led, 0);
|
||||
}
|
||||
|
||||
int led_toggle(led_control_t *ctx, led_id_t led)
|
||||
{
|
||||
if (!is_valid_led(led)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
uint8_t new_brightness = (ctx->brightness[led - 1] == 0) ? 255 : 0;
|
||||
return led_set_brightness(ctx, led, new_brightness);
|
||||
}
|
||||
|
||||
int led_update_all(led_control_t *ctx)
|
||||
{
|
||||
return htr3236_update(ctx->htr3236_dev, ctx->i2c);
|
||||
}
|
||||
|
||||
/*=========================================================================
|
||||
组控制API实现
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
int led_group_set_brightness(led_control_t *ctx,
|
||||
led_group_t group,
|
||||
uint8_t brightness)
|
||||
{
|
||||
uint8_t start, end;
|
||||
get_group_range(group, &start, &end);
|
||||
|
||||
if (group == LED_GROUP_FUNCTION) {
|
||||
// 功能LED需要单独处理每个LED
|
||||
led_id_t function_leds[] = {
|
||||
LED_MUSIC, LED_ANC, LED_FOOTSTEP_MODE, LED_AI7_1, LED_GAME_MODE
|
||||
};
|
||||
|
||||
for (int i = 0; i < 5; i++) {
|
||||
led_id_t led = function_leds[i];
|
||||
uint8_t physical_out = get_physical_out(led); // 如果有映射
|
||||
ctx->brightness[physical_out - 1] = brightness;
|
||||
htr3236_set_pwm(ctx->htr3236_dev, ctx->i2c, led, brightness);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (uint8_t led = start; led <= end; led++) {
|
||||
if (led == 36) continue; // 跳过未使用的OUT36
|
||||
if((group == LED_GROUP_L_SERIES) || (group == LED_GROUP_D_SERIES))
|
||||
{
|
||||
uint8_t physical_out = get_physical_out(led);
|
||||
ctx->brightness[physical_out - 1] = brightness;
|
||||
}
|
||||
else ctx->brightness[led - 1] = brightness;
|
||||
htr3236_set_pwm(ctx->htr3236_dev, ctx->i2c, led, brightness);
|
||||
}
|
||||
}
|
||||
|
||||
return htr3236_update(ctx->htr3236_dev, ctx->i2c);
|
||||
}
|
||||
|
||||
int led_group_on(led_control_t *ctx, led_group_t group)
|
||||
{
|
||||
return led_group_set_brightness(ctx, group, 255);
|
||||
}
|
||||
|
||||
int led_group_off(led_control_t *ctx, led_group_t group)
|
||||
{
|
||||
return led_group_set_brightness(ctx, group, 0);
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* @file led_control.h
|
||||
* @brief LED控制API (基于HTR3236)
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
#ifndef LED_CONTROL_H
|
||||
#define LED_CONTROL_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "htr3236.h"
|
||||
|
||||
#ifdef __XC__
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*=========================================================================
|
||||
LED类型定义
|
||||
-----------------------------------------------------------------------*/
|
||||
typedef enum {
|
||||
// 功能LED (单个LED)
|
||||
LED_MUSIC = 2, // OUT2 - 音乐模式
|
||||
LED_ANC = 1, // OUT1 - ANC模式
|
||||
LED_FOOTSTEP_MODE = 3, // OUT3 - 脚步模式
|
||||
LED_AI7_1 = 34, // OUT34 - AI7.1模式
|
||||
LED_GAME_MODE = 35, // OUT35 - 游戏模式
|
||||
// OUT36未使用
|
||||
|
||||
// L系列LED (OUT4-OUT18)
|
||||
LED_L1 = 4, LED_L2 = 5, LED_L3 = 6, LED_L4 = 7, LED_L5 = 8,
|
||||
LED_L6 = 9, LED_L7 = 10, LED_L8 = 11, LED_L9 = 12, LED_L10 = 13,
|
||||
LED_L11 = 14, LED_L12 = 15, LED_L13 = 16, LED_L14 = 17, LED_L15 = 18,
|
||||
|
||||
// D系列LED (OUT19-OUT33)
|
||||
LED_D1 = 19, LED_D2 = 20, LED_D3 = 21, LED_D4 = 22, LED_D5 = 23,
|
||||
LED_D6 = 24, LED_D7 = 25, LED_D8 = 26, LED_D9 = 27, LED_D10 = 28,
|
||||
LED_D11 = 29, LED_D12 = 30, LED_D13 = 31, LED_D14 = 32, LED_D15 = 33,
|
||||
|
||||
LED_MAX = 36
|
||||
} led_id_t;
|
||||
|
||||
/*=========================================================================
|
||||
LED组定义
|
||||
-----------------------------------------------------------------------*/
|
||||
typedef enum {
|
||||
LED_GROUP_L_SERIES, // L1-L15
|
||||
LED_GROUP_D_SERIES, // D1-D15
|
||||
LED_GROUP_FUNCTION, // 功能LED (ANC, MUSIC, FOOTSTEP, AI7_7, GAME)
|
||||
LED_GROUP_ALL // 所有LED
|
||||
} led_group_t;
|
||||
|
||||
/*=========================================================================
|
||||
LED控制上下文
|
||||
-----------------------------------------------------------------------*/
|
||||
typedef struct {
|
||||
htr3236_t *htr3236_dev; // HTR3236设备指针
|
||||
CLIENT_INTERFACE(i2c_master_if,i2c); // I2C接口
|
||||
uint8_t brightness[36]; // 当前亮度缓存
|
||||
} led_control_t;
|
||||
|
||||
/*=========================================================================
|
||||
LED物理映射表
|
||||
-----------------------------------------------------------------------*/
|
||||
// 逻辑LED编号到物理OUT口的映射表
|
||||
extern const uint8_t led_l_physical_map[15];
|
||||
extern const uint8_t led_d_physical_map[15];
|
||||
|
||||
extern const uint8_t mic_gain_to_led[39];
|
||||
|
||||
/*=========================================================================
|
||||
基础控制API
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief 初始化LED控制系统
|
||||
* @param ctx 上下文指针
|
||||
* @param dev HTR3236设备指针
|
||||
* @param i2c I2C接口
|
||||
*/
|
||||
void led_control_init(led_control_t *ctx,
|
||||
htr3236_t *dev,
|
||||
CLIENT_INTERFACE(i2c_master_if,i2c));
|
||||
|
||||
/**
|
||||
* @brief 设置单个LED亮度
|
||||
* @param ctx 上下文指针
|
||||
* @param led LED ID
|
||||
* @param brightness 亮度值 (0-255)
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int led_set_brightness(led_control_t *ctx,
|
||||
led_id_t led,
|
||||
uint8_t brightness);
|
||||
|
||||
/**
|
||||
* @brief 开启单个LED (最大亮度)
|
||||
* @param ctx 上下文指针
|
||||
* @param led LED ID
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int led_on(led_control_t *ctx, led_id_t led);
|
||||
|
||||
/**
|
||||
* @brief 关闭单个LED
|
||||
* @param ctx 上下文指针
|
||||
* @param led LED ID
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int led_off(led_control_t *ctx, led_id_t led);
|
||||
|
||||
/**
|
||||
* @brief 切换LED状态
|
||||
* @param ctx 上下文指针
|
||||
* @param led LED ID
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int led_toggle(led_control_t *ctx, led_id_t led);
|
||||
|
||||
/**
|
||||
* @brief 更新所有LED显示 (调用htr3236_update)
|
||||
* @param ctx 上下文指针
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int led_update_all(led_control_t *ctx);
|
||||
|
||||
/*=========================================================================
|
||||
组控制API
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief 设置一组LED的亮度
|
||||
* @param ctx 上下文指针
|
||||
* @param group LED组
|
||||
* @param brightness 亮度值 (0-255)
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int led_group_set_brightness(led_control_t *ctx,
|
||||
led_group_t group,
|
||||
uint8_t brightness);
|
||||
|
||||
/**
|
||||
* @brief 开启一组LED
|
||||
* @param ctx 上下文指针
|
||||
* @param group LED组
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int led_group_on(led_control_t *ctx, led_group_t group);
|
||||
|
||||
/**
|
||||
* @brief 关闭一组LED
|
||||
* @param ctx 上下文指针
|
||||
* @param group LED组
|
||||
* @return 0:成功, -1:失败
|
||||
*/
|
||||
int led_group_off(led_control_t *ctx, led_group_t group);
|
||||
|
||||
#ifdef __XC__
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* LED_CONTROL_H */
|
||||
@@ -0,0 +1,13 @@
|
||||
#ifndef _LFS_IO_H_
|
||||
#define _LFS_IO_H_
|
||||
int lfs_init(void);
|
||||
void lfs_deinit(void);
|
||||
void lfs_read_config(unsigned char * config, unsigned char * buffer, unsigned size);
|
||||
void lfs_write_config(unsigned char * config, unsigned char * buffer, unsigned size);
|
||||
// EQ参数专用函数
|
||||
void lfs_read_eq_config(const char * file_path, unsigned char * buffer, unsigned size);
|
||||
void lfs_write_eq_config(const char * file_path, unsigned char * buffer, unsigned size);
|
||||
int lfs_file_exists(const char * file_path);
|
||||
int lfs_remove_file(const char * file_path);
|
||||
int lfs_create_directory(const char * dir_path);
|
||||
#endif
|
||||
@@ -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 0x1a0000
|
||||
#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
|
||||
@@ -0,0 +1,733 @@
|
||||
// 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
|
||||
|
||||
|
||||
/* 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
|
||||
|
||||
par
|
||||
{
|
||||
USER_MAIN_CORES
|
||||
|
||||
#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)
|
||||
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
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
*
|
||||
* nau88c22.h
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef NAU88C22_H_
|
||||
#define NAU88C22_H_
|
||||
|
||||
uint16_t nau88c22_registers[][4] = {
|
||||
{0x00, 0x00, 0x00, 0x00},
|
||||
{0x00, 0x01, 0x0D, 0xFF},
|
||||
{0x00, 0x03, 0x20, 0x50},
|
||||
{0x00, 0x04, 0x00, 0x00},
|
||||
{0x00, 0x05, 0x00, 0xBC},
|
||||
{0x00, 0x06, 0x00, 0x08},
|
||||
{0x00, 0x07, 0x00, 0x10},
|
||||
{0x00, 0x08, 0x40, 0x00},
|
||||
{0x00, 0x09, 0x69, 0x00},
|
||||
{0x00, 0x0A, 0x00, 0x31},
|
||||
{0x00, 0x0B, 0x26, 0xE9},
|
||||
{0x00, 0x0D, 0xC0, 0x00},
|
||||
{0x00, 0x0F, 0x00, 0x00},
|
||||
{0x00, 0x10, 0x00, 0x00},
|
||||
{0x00, 0x11, 0x00, 0x00},
|
||||
{0x00, 0x12, 0xFF, 0xFF},
|
||||
{0x00, 0x13, 0x00, 0x00},
|
||||
{0x00, 0x1A, 0x00, 0x00},
|
||||
{0x00, 0x1B, 0x00, 0x00},
|
||||
{0x00, 0x1C, 0x00, 0x0E},
|
||||
{0x00, 0x1D, 0x20, 0x02},
|
||||
{0x00, 0x1E, 0x00, 0x00},
|
||||
{0x00, 0x1F, 0x00, 0x00},
|
||||
{0x00, 0x21, 0x00, 0x00},
|
||||
{0x00, 0x22, 0x00, 0x00},
|
||||
{0x00, 0x23, 0x00, 0x00},
|
||||
{0x00, 0x24, 0x00, 0x00},
|
||||
{0x00, 0x25, 0x00, 0x00},
|
||||
{0x00, 0x26, 0x00, 0x00},
|
||||
{0x00, 0x27, 0x00, 0x00},
|
||||
{0x00, 0x28, 0x00, 0x00},
|
||||
{0x00, 0x29, 0x00, 0x00},
|
||||
{0x00, 0x2A, 0x00, 0x00},
|
||||
{0x00, 0x2B, 0x40, 0x02}, // ADC Right Channel Source Select, bit 3, set to 1, 3rd byte 0x40 = Latch left channel analog data input into the right channel filter
|
||||
{0x00, 0x2C, 0x00, 0x82},
|
||||
{0x00, 0x2D, 0x00, 0x00},
|
||||
{0x00, 0x2F, 0x00, 0x00},
|
||||
{0x00, 0x30, 0x00, 0x40},
|
||||
{0x00, 0x31, 0x00, 0x00},
|
||||
{0x00, 0x32, 0x00, 0x00},
|
||||
{0x00, 0x34, 0xCF, 0xCF},
|
||||
{0x00, 0x35, 0xCF, 0xCF},
|
||||
{0x00, 0x36, 0x14, 0x86},
|
||||
{0x00, 0x37, 0x0F, 0x12},
|
||||
{0x00, 0x38, 0x25, 0xFF},
|
||||
{0x00, 0x39, 0x34, 0x57},
|
||||
{0x00, 0x3A, 0x14, 0x86},
|
||||
{0x00, 0x3B, 0x0F, 0x12},
|
||||
{0x00, 0x3C, 0x25, 0xF9},
|
||||
{0x00, 0x3D, 0x34, 0x57},
|
||||
{0x00, 0x41, 0x00, 0x00},
|
||||
{0x00, 0x42, 0x00, 0x00},
|
||||
{0x00, 0x43, 0x00, 0x00},
|
||||
{0x00, 0x44, 0x00, 0x00},
|
||||
{0x00, 0x45, 0x00, 0x00},
|
||||
{0x00, 0x46, 0x00, 0x00},
|
||||
{0x00, 0x47, 0x00, 0x00},
|
||||
{0x00, 0x48, 0x00, 0x00},
|
||||
{0x00, 0x49, 0x00, 0x00},
|
||||
{0x00, 0x4A, 0x00, 0x00},
|
||||
{0x00, 0x4B, 0x20, 0x07},
|
||||
{0x00, 0x4C, 0x00, 0x00},
|
||||
{0x00, 0x4D, 0x00, 0x00},
|
||||
{0x00, 0x53, 0x02, 0x78},
|
||||
{0x00, 0x54, 0x00, 0x02},
|
||||
{0x00, 0x55, 0x00, 0x00},
|
||||
{0x00, 0x58, 0x1B, 0x22},
|
||||
{0x00, 0x59, 0x20, 0x00},
|
||||
{0x00, 0x66, 0x00, 0x60},
|
||||
{0x00, 0x68, 0x00, 0x00},
|
||||
{0x00, 0x69, 0x00, 0x00},
|
||||
{0x00, 0x6A, 0x10, 0x03},
|
||||
{0x00, 0x6B, 0x00, 0x00},
|
||||
{0x00, 0x71, 0x00, 0x11},
|
||||
{0x00, 0x72, 0x04, 0x70},
|
||||
{0x00, 0x73, 0x33, 0x08},
|
||||
{0x00, 0x74, 0x15, 0x06},
|
||||
{0x00, 0x76, 0x31, 0x40},
|
||||
{0x00, 0x77, 0x00, 0x12},
|
||||
{0x00, 0x7E, 0x01, 0x01},
|
||||
{0x00, 0x7F, 0xC0, 0x3F},
|
||||
{0x00, 0x80, 0x07, 0x20},
|
||||
{0x00, 0x81, 0x00, 0x08},
|
||||
{0x00, 0x82, 0x00, 0x60},
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,652 @@
|
||||
#define DEBUG_PRINT_ENABLE 0
|
||||
#include <stdint.h>
|
||||
#include "debug_print.h"
|
||||
#include <quadflashlib.h>
|
||||
#include <xcore/chanend.h>
|
||||
#include <xcore/channel.h>
|
||||
#include "xua_conf.h"
|
||||
|
||||
#define WRITE_ENABLE_COMMAND (0x06)
|
||||
#define WRITE_DISABLE_COMMAND (0x04)
|
||||
|
||||
#define ERASE_CHIP_COMMAND (0xC7)
|
||||
|
||||
|
||||
#define READ_STATUS_REG_COMMAND (0x05)
|
||||
#define READ_ID_COMMAND (0x9F)
|
||||
|
||||
#define READ_UID_COMMAND (0x4B)
|
||||
|
||||
#define WRITE_ENABLE_STATUS_COMMAND (0x50)
|
||||
|
||||
#define WRITE_STATUS_REG1_COMMAND (0x01)
|
||||
#define READ_STATUS_REG2_COMMAND (0x35)
|
||||
#define WRITE_STATUS_REG2_COMMAND (0x31)
|
||||
#define READ_STATUS_REG3_COMMAND (0x15)
|
||||
#define WRITE_STATUS_REG3_COMMAND (0x11)
|
||||
|
||||
#define RDSTATUS_COMMAND (0x35)
|
||||
#define WRSTATUS_COMMAND (0x31)
|
||||
|
||||
#define PRSCUR_COMMAND (0x42)
|
||||
#define ERSCUR_COMMAND (0x44)
|
||||
#define RDSCUR_COMMAND (0x48)
|
||||
#define HMAC_LEN 60
|
||||
#define HMAC_GEN_LEN 20
|
||||
|
||||
|
||||
extern unsigned short XUA_Endpoint0_getProductId();
|
||||
extern unsigned short XUA_Endpoint0_getVendorId();
|
||||
|
||||
unsigned char hid_reply[64] = {0};
|
||||
|
||||
#if 0
|
||||
void printArrayHex1(uint8_t array[], int size, int elementsPerLine) {
|
||||
for (int i = 0; i < size; i++) {
|
||||
printf("0x%x, ", array[i]);
|
||||
|
||||
// 在达到每行元素个数时换行
|
||||
if ((i + 1) % elementsPerLine == 0) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
#define settw(a,b) {__asm__ __volatile__("settw res[%0], %1": : "r" (a) , "r" (b));}
|
||||
#define setc(a,b) {__asm__ __volatile__("setc res[%0], %1": : "r" (a) , "r" (b));}
|
||||
#define setclk(a,b) {__asm__ __volatile__("setclk res[%0], %1": : "r" (a) , "r" (b));}
|
||||
#define portin(a,b) {__asm__ __volatile__("in %0, res[%1]": "=r" (b) : "r" (a));}
|
||||
#define portout(a,b) {__asm__ __volatile__("out res[%0], %1": : "r" (a) , "r" (b));}
|
||||
|
||||
#ifdef DFU_FLASH_DEVICE
|
||||
|
||||
#if (XUA_QUAD_SPI_FLASH)
|
||||
/* Using specified flash device rather than all supported in tools */
|
||||
fl_QuadDeviceSpec opt_flash_devices[] = {DFU_FLASH_DEVICE};
|
||||
#else
|
||||
/* Using specified flash device rather than all supported in tools */
|
||||
fl_DeviceSpec opt_flash_devices[] = {DFU_FLASH_DEVICE};
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
typedef struct {
|
||||
out port qspiCS;
|
||||
out port qspiSCLK;
|
||||
out buffered port:32 qspiSIO;
|
||||
clock qspiClkblk;
|
||||
} fl_QSPIPorts;
|
||||
*/
|
||||
fl_QSPIPorts p_opt_qflash_tile0 =
|
||||
{
|
||||
XS1_PORT_1B,
|
||||
XS1_PORT_1C,
|
||||
XS1_PORT_4B,
|
||||
XS1_CLKBLK_1
|
||||
};
|
||||
|
||||
fl_QSPIPorts p_opt_qflash_tile1 =
|
||||
{
|
||||
XS1_PORT_1F,
|
||||
XS1_PORT_1G,
|
||||
XS1_PORT_4D,
|
||||
XS1_CLKBLK_1
|
||||
};
|
||||
|
||||
#define KEY_ADDRESS 0xFFFD0
|
||||
|
||||
/* Store Flag to fixed address */
|
||||
static void SetKeyFlag(unsigned x)
|
||||
{
|
||||
asm volatile("stw %0, %1[0]" :: "r"(x), "r"(KEY_ADDRESS));
|
||||
}
|
||||
|
||||
/* Load flag from fixed address */
|
||||
unsigned GetKeyFlag()
|
||||
{
|
||||
unsigned x;
|
||||
asm volatile("ldw %0, %1[0]" : "=r"(x) : "r"(KEY_ADDRESS));
|
||||
return x;
|
||||
}
|
||||
|
||||
/* return 1 for opened ports successfully */
|
||||
int flash_opt_enable_ports(fl_QSPIPorts *p_qflash)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
#ifdef DFU_FLASH_DEVICE
|
||||
result = fl_connectToDevice(p_qflash, opt_flash_devices, sizeof(opt_flash_devices) / sizeof(fl_QuadDeviceSpec));
|
||||
#else
|
||||
/* Use default flash list */
|
||||
result = fl_connect(p_qflash);
|
||||
#endif
|
||||
if (!result)
|
||||
{
|
||||
/* All okay.. */
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int flash_opt_disable_ports()
|
||||
{
|
||||
fl_disconnect();
|
||||
return 1;
|
||||
}
|
||||
|
||||
void flash_cmd_opt(unsigned int cmd,
|
||||
unsigned char input[], unsigned int num_in,
|
||||
unsigned char output[], unsigned int num_out)
|
||||
{
|
||||
debug_printf("flash_cmd_opt: cmd = %02x, num_in = %d, num_out = %d\n", cmd, num_in, num_out);
|
||||
for (size_t i = 0; i < num_in; i++)
|
||||
{
|
||||
debug_printf("input[%d] = %02x\n", i, input[i]);
|
||||
}
|
||||
for (size_t i = 0; i < num_out; i++)
|
||||
{
|
||||
debug_printf("output[%d] = %02x\n", i, output[i]);
|
||||
}
|
||||
fl_command(cmd,input,num_in,output, num_out);
|
||||
}
|
||||
|
||||
void flash_opt_erase()
|
||||
{
|
||||
uint8_t cmd[4] = {0, 0x10, 0x0, 0};
|
||||
uint8_t data[4] = {0, 0x10, 0x0, 0};
|
||||
flash_cmd_opt(WRITE_ENABLE_COMMAND, cmd, 0, data, 0);
|
||||
delay_milliseconds(1);
|
||||
flash_cmd_opt(ERSCUR_COMMAND, cmd, 3, data, 0);
|
||||
delay_milliseconds(50);
|
||||
}
|
||||
|
||||
void flash_opt_read_did(uint8_t data[], unsigned char len)
|
||||
{
|
||||
uint8_t cmd[3] = {0x3, 0x10, 0x0};
|
||||
|
||||
flash_cmd_opt(READ_ID_COMMAND, cmd, 0, data, len);
|
||||
// printArrayHex1(data, len, 20);
|
||||
}
|
||||
|
||||
|
||||
void flash_opt_unlock(void)
|
||||
{
|
||||
uint8_t cmd[1] = {0};
|
||||
uint8_t data[1] = {0};
|
||||
uint8_t sr1, sr2, sr3;
|
||||
uint8_t did[3];
|
||||
|
||||
/* Reason: 使用 tile0 端口连接 Flash,保持原有逻辑 */
|
||||
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0) {
|
||||
debug_printf("flash_opt_unlock failed\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/* Reason: 增加 Flash 厂商ID检查,仅针对 Winbond (0xEF) 执行特定解锁逻辑 */
|
||||
flash_opt_read_did(did, 3);
|
||||
if (did[0] != 0xEF)
|
||||
{
|
||||
debug_printf("Not Winbond flash (DID: %02x), skip unlock\n", did[0]);
|
||||
flash_opt_disable_ports();
|
||||
return;
|
||||
}
|
||||
|
||||
debug_printf("Unlock Winbond Flash...\n");
|
||||
|
||||
/* Reason: 解锁 Status Register 1。
|
||||
参考 flash_api_ext.c 逻辑,清除 Bit 2-6 (BP0-BP4, TB, SEC)
|
||||
Mask: 0x7C (0111 1100) */
|
||||
flash_cmd_opt(READ_STATUS_REG_COMMAND, cmd, 0, data, 1);
|
||||
sr1 = data[0];
|
||||
if (sr1 & 0x7C)
|
||||
{
|
||||
debug_printf("Unlock SR1: %02x -> %02x\n", sr1, sr1 & ~0x7C);
|
||||
flash_cmd_opt(WRITE_ENABLE_STATUS_COMMAND, cmd, 0, data, 0);
|
||||
data[0] = sr1 & ~0x7C;
|
||||
flash_cmd_opt(WRITE_STATUS_REG1_COMMAND, data, 1, cmd, 0);
|
||||
delay_milliseconds(10); /* 等待写入完成 */
|
||||
}
|
||||
|
||||
/* Reason: 解锁 Status Register 2。
|
||||
参考 flash_api_ext.c 逻辑,清除 Bit 6 (CMP)
|
||||
Mask: 0x40 (0100 0000) */
|
||||
flash_cmd_opt(READ_STATUS_REG2_COMMAND, cmd, 0, data, 1);
|
||||
sr2 = data[0];
|
||||
if ((sr2 & 0x40) || ((sr2 & 0x2) == 0))
|
||||
{
|
||||
debug_printf("Unlock SR2: %02x -> %02x\n", sr2, (sr2 & ~0x40) | 0x2);
|
||||
flash_cmd_opt(WRITE_ENABLE_STATUS_COMMAND, cmd, 0, data, 0);
|
||||
data[0] = (sr2 & ~0x40) | 0x2;
|
||||
flash_cmd_opt(WRITE_STATUS_REG2_COMMAND, data, 1, cmd, 0);
|
||||
delay_milliseconds(10);
|
||||
}
|
||||
|
||||
/* Reason: 解锁 Status Register 3。
|
||||
参考 flash_api_ext.c 逻辑,清除 Bit 2 (WPS)
|
||||
Mask: 0x04 (0000 0100) */
|
||||
flash_cmd_opt(READ_STATUS_REG3_COMMAND, cmd, 0, data, 1);
|
||||
sr3 = data[0];
|
||||
if (sr3 & 0x04)
|
||||
{
|
||||
debug_printf("Unlock SR3: %02x -> %02x\n", sr3, sr3 & ~0x04);
|
||||
flash_cmd_opt(WRITE_ENABLE_STATUS_COMMAND, cmd, 0, data, 0);
|
||||
data[0] = sr3 & ~0x04;
|
||||
flash_cmd_opt(WRITE_STATUS_REG3_COMMAND, data, 1, cmd, 0);
|
||||
delay_milliseconds(10);
|
||||
}
|
||||
|
||||
flash_opt_disable_ports();
|
||||
debug_printf("Unlock Winbond Flash done\n");
|
||||
}
|
||||
|
||||
void flash_opt_write2(uint8_t data[], unsigned char len)
|
||||
{
|
||||
uint8_t d[1];
|
||||
uint8_t cmd[256] = {0, 0x10, 0x0};
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
cmd[i + 3] = data[i];
|
||||
}
|
||||
|
||||
flash_opt_erase();
|
||||
flash_cmd_opt(WRITE_ENABLE_COMMAND, cmd, 0, d, 0);
|
||||
flash_cmd_opt(PRSCUR_COMMAND, cmd, 3 + len, d, 0);
|
||||
delay_milliseconds(50);
|
||||
}
|
||||
|
||||
void flash_opt_read(uint8_t data[], unsigned char len)
|
||||
{
|
||||
uint8_t cmd[3] = {0x00, 0x10, 0x00};
|
||||
|
||||
flash_cmd_opt(RDSCUR_COMMAND, cmd, 3, data, len);
|
||||
//printf("read sec key:\n");
|
||||
//printArrayHex1(data, len, 20);
|
||||
}
|
||||
|
||||
void flash_opt_read_uid(uint8_t data[], unsigned char len)
|
||||
{
|
||||
uint8_t cmd[3] = {0x3, 0x10, 0x0};
|
||||
|
||||
flash_cmd_opt(READ_UID_COMMAND, cmd, 0, data, len);
|
||||
// printArrayHex1(data, len, 20);
|
||||
}
|
||||
|
||||
|
||||
|
||||
unsigned compare_buff_diff(const uint8_t* actual, const uint8_t* expected, unsigned len)
|
||||
{
|
||||
for (int i = 0; i < len; ++i)
|
||||
{
|
||||
if (actual[i] != expected[i])
|
||||
{
|
||||
debug_printf("compare_buff_diff: %d %02x %02x\n", i, actual[i], expected[i]);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
extern void hmac_sha1(const unsigned char *, unsigned long, const unsigned char * , unsigned long, unsigned char * );
|
||||
|
||||
void cal_hmac(uint8_t uid[], uint8_t did[], uint8_t hmac_bin[])
|
||||
{
|
||||
{
|
||||
uint8_t key_bin[HMAC_GEN_LEN] = {0x76, 0x37, 0x0b, 0xb8, 0xbd, 0xe5, 0x54, 0x82, 0x8f, 0x13, 0x29, 0xa6, 0x26, 0x07, 0x2d, 0xe1, 0x11, 0x6c, 0xfb, 0x07};
|
||||
uint8_t msg_bin[HMAC_GEN_LEN];
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
msg_bin[i] = did[i];
|
||||
}
|
||||
|
||||
for (int i = 3; i < 20; i++)
|
||||
{
|
||||
msg_bin[i] = uid[i];
|
||||
}
|
||||
|
||||
#if 0
|
||||
printf("msg_bin: \n");
|
||||
printArrayHex1(msg_bin, HMAC_GEN_LEN, 20);
|
||||
#endif
|
||||
hmac_sha1(key_bin, HMAC_GEN_LEN, msg_bin, HMAC_GEN_LEN, hmac_bin);
|
||||
|
||||
#if 0
|
||||
printf("hmac_bin: \n");
|
||||
printArrayHex1(hmac_bin, HMAC_LEN, 20);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t key_verify_old(unsigned sec_write, uint8_t expected_bin[], unsigned offset)
|
||||
{
|
||||
uint8_t read_bin[HMAC_LEN + 1];
|
||||
uint8_t comp_bin[HMAC_LEN + 1];
|
||||
uint8_t uid[20];
|
||||
uint8_t did[4];
|
||||
uint8_t ret = 0;
|
||||
uint8_t hmac_bin[20];
|
||||
|
||||
flash_opt_read(read_bin, HMAC_LEN + 1);
|
||||
flash_opt_read_uid(uid, 20);
|
||||
flash_opt_read_did(did, 3);
|
||||
|
||||
cal_hmac(uid, did, hmac_bin);
|
||||
|
||||
if (sec_write)
|
||||
{
|
||||
if (offset == 0)
|
||||
{
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
read_bin[i + 1] = expected_bin[i];
|
||||
}
|
||||
}
|
||||
else if (offset == 1)
|
||||
{
|
||||
for (int i = 0; i < 20; i++)
|
||||
{
|
||||
read_bin[i + 21] = expected_bin[i];
|
||||
}
|
||||
}
|
||||
|
||||
flash_opt_write2(&read_bin[1], HMAC_LEN);
|
||||
delay_milliseconds(10);
|
||||
|
||||
flash_opt_read(comp_bin, HMAC_LEN + 1);
|
||||
if (compare_buff_diff(&comp_bin[1], &read_bin[1], HMAC_LEN) == 1)
|
||||
{
|
||||
debug_printf("compare OK\n");
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (offset == 0)
|
||||
{
|
||||
flash_opt_read(read_bin, HMAC_LEN + 1);
|
||||
if (compare_buff_diff(hmac_bin, &read_bin[1], 20) == 1)
|
||||
{
|
||||
debug_printf("key_verified\n");
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
else if (offset == 1)
|
||||
{
|
||||
flash_opt_read(read_bin, HMAC_LEN + 1);
|
||||
if (compare_buff_diff(hmac_bin, &read_bin[21], 20) == 1)
|
||||
{
|
||||
debug_printf("key_verified\n");
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void flash_read_uid(uint8_t *uid)
|
||||
{
|
||||
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
flash_opt_read_uid(uid, 20);
|
||||
flash_opt_disable_ports();
|
||||
}
|
||||
|
||||
void flash_read_did(uint8_t *did)
|
||||
{
|
||||
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
flash_opt_read_did(did, 3);
|
||||
flash_opt_disable_ports();
|
||||
}
|
||||
|
||||
void get_key_ret(uint8_t *buffer)
|
||||
{
|
||||
//printf("get_key_ret2\n");
|
||||
for (int i = 0; i < 64; i ++)
|
||||
{
|
||||
buffer[i] = hid_reply[i];
|
||||
hid_reply[i] = 0;
|
||||
}
|
||||
|
||||
//printArrayHex1(buffer, 20, 20);
|
||||
}
|
||||
|
||||
unsigned char g_hid_pass_data[64];
|
||||
extern void hidSetChangePending(unsigned int);
|
||||
|
||||
void user_read_hidpass(unsigned char * hidPassData)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < 64; i++)
|
||||
{
|
||||
hidPassData[i] = g_hid_pass_data[i];
|
||||
debug_printf("hidPassData[%d] = %02x\n", i, hidPassData[i]);
|
||||
g_hid_pass_data[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void user_set_hidpass(unsigned char *data)
|
||||
{
|
||||
#if HID_CONTROLS
|
||||
|
||||
for (int i = 0; i < 63; i++)
|
||||
{
|
||||
g_hid_pass_data[i] = data[i];
|
||||
debug_printf("g_hid_pass_data[%d] = %02x\n", i, g_hid_pass_data[i]);
|
||||
}
|
||||
|
||||
hidSetChangePending(0x1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static chanend_t g_flash_opt_c;
|
||||
|
||||
void flash_opt_set_chan(chanend_t c) {
|
||||
g_flash_opt_c = c;
|
||||
//debug_printf("flash_opt_set_chan\n");
|
||||
}
|
||||
|
||||
void flash_opt_exchange_buffer(uint8_t in[64], uint8_t out[64]) {
|
||||
//debug_printf("flash_opt_exchange_buffer\n");
|
||||
chan_out_buf_byte (g_flash_opt_c , in, 40) ;
|
||||
//debug_printf("flash_opt_exchange_buffer1\n");
|
||||
chan_in_buf_byte(g_flash_opt_c, out, 40);
|
||||
}
|
||||
|
||||
void flash_opt_key(chanend_t c) {
|
||||
uint8_t buffer[64], reply[40] = {0, 0, 0, 0};
|
||||
uint32_t ret;
|
||||
delay_milliseconds(2);
|
||||
while (1) {
|
||||
chan_in_buf_byte(c, buffer, 40);
|
||||
if (flash_opt_enable_ports(&p_opt_qflash_tile1) == 0) {
|
||||
reply[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (buffer[3])
|
||||
{
|
||||
case 9:
|
||||
flash_opt_read_did(&reply[1], 3);
|
||||
reply[0] = 0x55;
|
||||
break;
|
||||
case 10:
|
||||
flash_opt_read_uid(&reply[1], 21);
|
||||
reply[0] = 0x55;
|
||||
break;
|
||||
case 8:
|
||||
ret = key_verify_old(1, &buffer[4], 0);
|
||||
if (ret == 1)
|
||||
{
|
||||
debug_printf("write key ret 0x55\n");
|
||||
reply[0] = 0x55;
|
||||
}
|
||||
else
|
||||
{
|
||||
reply[0] = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
flash_opt_disable_ports();
|
||||
chan_out_buf_byte(c, reply, 40) ;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint8_t key_validate(void)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
uint8_t data[1] = {0};
|
||||
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
ret = key_verify_old(0, data, 0);
|
||||
if (ret == 1)
|
||||
{
|
||||
SetKeyFlag(0x20241224);
|
||||
}
|
||||
|
||||
ret = key_verify_old(0, data, 1);
|
||||
if (ret == 1)
|
||||
{
|
||||
SetKeyFlag(0x20241224);
|
||||
}
|
||||
flash_opt_disable_ports();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void program_key(uint8_t *buffer, int datalength)
|
||||
{
|
||||
if (buffer[0] == 0x77 && buffer[1] == 0x5B)
|
||||
{
|
||||
uint8_t ret = 0;
|
||||
switch (buffer[2])
|
||||
{
|
||||
case 1:
|
||||
debug_printf("verify key\n");
|
||||
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
|
||||
{
|
||||
hid_reply[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t data[1] = {0};
|
||||
ret = key_verify_old(0, data, 0);
|
||||
if (ret == 1)
|
||||
{
|
||||
hid_reply[0] = 0x55;
|
||||
}
|
||||
else
|
||||
{
|
||||
hid_reply[0] = 0;
|
||||
}
|
||||
flash_opt_disable_ports();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
debug_printf("write key\n");
|
||||
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
|
||||
{
|
||||
hid_reply[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = key_verify_old(1, &buffer[3], 0);
|
||||
|
||||
debug_printf("write key ret %d\n", ret);
|
||||
if (ret == 1)
|
||||
{
|
||||
hid_reply[0] = 0x55;
|
||||
}
|
||||
else
|
||||
{
|
||||
hid_reply[0] = 0;
|
||||
}
|
||||
flash_opt_disable_ports();
|
||||
}
|
||||
|
||||
break;
|
||||
case 3:
|
||||
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
|
||||
{
|
||||
hid_reply[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
flash_opt_read_did(&hid_reply[1], 3);
|
||||
debug_printf("return did\n");
|
||||
hid_reply[0] = 0x55;
|
||||
flash_opt_disable_ports();
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
|
||||
{
|
||||
hid_reply[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_printf("return uid\n");
|
||||
flash_opt_read_uid(&hid_reply[1], 21);
|
||||
hid_reply[0] = 0x55;
|
||||
flash_opt_disable_ports();
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
if (flash_opt_enable_ports(&p_opt_qflash_tile0) == 0)
|
||||
{
|
||||
hid_reply[0] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_printf("erase key\n");
|
||||
flash_opt_erase();
|
||||
hid_reply[0] = 0x55;
|
||||
flash_opt_disable_ports();
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
debug_printf("get pid vid\n");
|
||||
unsigned short pid = XUA_Endpoint0_getProductId();
|
||||
unsigned short vid = XUA_Endpoint0_getVendorId();
|
||||
hid_reply[2] = (pid >> 8) & 0xff;
|
||||
hid_reply[1] = pid & 0xff;
|
||||
hid_reply[4] = (vid >> 8) & 0xff;
|
||||
hid_reply[3] = vid & 0xff;
|
||||
hid_reply[0] = 0x55;
|
||||
break;
|
||||
case 7:
|
||||
break;
|
||||
case 8:
|
||||
case 9:
|
||||
case 10:
|
||||
//flash_opt_exchange_buffer(buffer, hid_reply);
|
||||
// debug_printf("write aizip key tile 0 %02x\n", hid_reply[0]);
|
||||
for (int i = 0; i < datalength; i++)
|
||||
hid_reply[i] = 0;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//xmos_printf(&buffer[1], datalength - 1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
#include "share_buffer.h"
|
||||
#define RING_BUFFER_SIZE 512
|
||||
|
||||
typedef struct {
|
||||
int buffer[RING_BUFFER_SIZE];
|
||||
int head;
|
||||
int tail;
|
||||
int count;
|
||||
} RingBuffer;
|
||||
|
||||
// 两路环形缓冲区
|
||||
RingBuffer ring_buffers[4];
|
||||
|
||||
// 初始化环形缓冲区
|
||||
void init_ring_buffer(int channel) {
|
||||
if (channel < 0 || channel > 1) return;
|
||||
|
||||
ring_buffers[channel].head = 0;
|
||||
ring_buffers[channel].tail = 0;
|
||||
ring_buffers[channel].count = 0;
|
||||
}
|
||||
|
||||
// 初始化所有环形缓冲区
|
||||
void init_all_ring_buffers() {
|
||||
init_ring_buffer(0);
|
||||
init_ring_buffer(1);
|
||||
}
|
||||
|
||||
// 判断环形缓冲区是否为空
|
||||
int is_ring_buffer_empty(int channel) {
|
||||
if (channel < 0 || channel > 3) return 1;
|
||||
|
||||
return (ring_buffers[channel].count == 0);
|
||||
}
|
||||
|
||||
// 判断环形缓冲区是否已满
|
||||
int is_ring_buffer_full(int channel) {
|
||||
if (channel < 0 || channel > 3) return 0;
|
||||
|
||||
return (ring_buffers[channel].count == RING_BUFFER_SIZE);
|
||||
}
|
||||
|
||||
// 获取环形缓冲区中的数据数量
|
||||
int get_ring_buffer_count(int channel) {
|
||||
if (channel < 0 || channel > 3) return 0;
|
||||
|
||||
return ring_buffers[channel].count;
|
||||
}
|
||||
|
||||
// 向环形缓冲区写入数据
|
||||
int write_to_ring_buffer(int channel, int value) {
|
||||
if (channel < 0 || channel > 3) return -1;
|
||||
|
||||
if (is_ring_buffer_full(channel)) {
|
||||
return -1; // 缓冲区已满
|
||||
}
|
||||
|
||||
ring_buffers[channel].buffer[ring_buffers[channel].head] = value;
|
||||
ring_buffers[channel].head = (ring_buffers[channel].head + 1) % RING_BUFFER_SIZE;
|
||||
ring_buffers[channel].count++;
|
||||
|
||||
return 0; // 写入成功
|
||||
}
|
||||
|
||||
// 从环形缓冲区读取数据
|
||||
int read_from_ring_buffer(int channel) {
|
||||
int value = 0;
|
||||
if (channel == 0 || channel == 1 || channel == 2 || channel == 3) {
|
||||
if (is_ring_buffer_empty(channel)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
value = ring_buffers[channel].buffer[ring_buffers[channel].tail];
|
||||
ring_buffers[channel].tail = (ring_buffers[channel].tail + 1) % RING_BUFFER_SIZE;
|
||||
ring_buffers[channel].count--;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
// 清空环形缓冲区
|
||||
void clear_ring_buffer(int channel) {
|
||||
if (channel < 0 || channel > 3) return;
|
||||
|
||||
ring_buffers[channel].head = 0;
|
||||
ring_buffers[channel].tail = 0;
|
||||
ring_buffers[channel].count = 0;
|
||||
}
|
||||
|
||||
// 清空所有环形缓冲区
|
||||
void clear_all_ring_buffers() {
|
||||
clear_ring_buffer(0);
|
||||
clear_ring_buffer(1);
|
||||
clear_ring_buffer(2);
|
||||
clear_ring_buffer(3);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
|
||||
void init_ring_buffer(int channel);
|
||||
void init_all_ring_buffers();
|
||||
int is_ring_buffer_empty(int channel);
|
||||
int is_ring_buffer_full(int channel);
|
||||
int get_ring_buffer_count(int channel);
|
||||
int write_to_ring_buffer(int channel, int value);
|
||||
int read_from_ring_buffer(int channel);
|
||||
void clear_ring_buffer(int channel);
|
||||
void clear_all_ring_buffers();
|
||||
@@ -0,0 +1,233 @@
|
||||
|
||||
#if UART_DEBUG || DEBUG_MEMORY_LOG_ENABLED
|
||||
#define DEBUG_PRINT_ENABLE 1
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "user_func.h"
|
||||
#include "lfs_io.h"
|
||||
#include "debug_print.h"
|
||||
|
||||
ProductInfo productInfo;
|
||||
AppConfigs appPowerOnConf, appRunningState, appUserConf;
|
||||
AudioMode appAudioMode;
|
||||
|
||||
#define PRODUCT_INFO_PATH "product_info"
|
||||
#define POWERON_INFO_PATH "poweron_info"
|
||||
|
||||
uint32_t calculate_crc32(uint8_t *buf, int len) {
|
||||
uint32_t crc = 0xFFFFFFFF;
|
||||
uint32_t poly = 0xEDB88320;
|
||||
for (int i = 0; i < len; i++) {
|
||||
crc ^= (uint32_t)buf[i];
|
||||
for (int j = 8; j > 0; j--) {
|
||||
if (crc & 1) {
|
||||
crc = (crc >> 1) ^ poly;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
unsigned char check_sum(unsigned char *pbuf, unsigned len)
|
||||
{
|
||||
unsigned char i;
|
||||
unsigned short sum;
|
||||
sum = 0;
|
||||
for(i = 0; i < len; i++)
|
||||
{
|
||||
sum += pbuf[i];
|
||||
}
|
||||
i = sum % 256;
|
||||
return i;
|
||||
}
|
||||
|
||||
uint32_t get_reference_time();
|
||||
void load_configs(void)
|
||||
{
|
||||
//uint32_t t = get_reference_time();
|
||||
if (lfs_init() == 0)
|
||||
{
|
||||
lfs_read_config(PRODUCT_INFO_PATH, (unsigned char*) &productInfo, sizeof(productInfo));
|
||||
lfs_read_config(POWERON_INFO_PATH, (unsigned char*) &appPowerOnConf, sizeof(appPowerOnConf));
|
||||
//printf("load configs\n");
|
||||
// printf("load pid 0x%04x vid 0x%04x\n", productInfo.pid2, productInfo.vid2);
|
||||
}
|
||||
lfs_deinit();
|
||||
//printf("bytes read time %lu\n", get_reference_time() - t);
|
||||
}
|
||||
|
||||
void save_configs(unsigned char save)
|
||||
{
|
||||
if (save != 0)
|
||||
{
|
||||
//uint32_t t = get_reference_time();
|
||||
if (lfs_init() == 0)
|
||||
{
|
||||
if (save & 0x1)
|
||||
lfs_write_config(PRODUCT_INFO_PATH, (unsigned char*) &productInfo, sizeof(productInfo));
|
||||
if (save & 0x2)
|
||||
lfs_write_config(POWERON_INFO_PATH, (unsigned char*) &appPowerOnConf, sizeof(appPowerOnConf));
|
||||
}
|
||||
|
||||
//printf("save ... pid 0x%04x vid 0x%04x\n", productInfo.pid2, productInfo.vid2);
|
||||
lfs_deinit();
|
||||
//printf("bytes write time %lu\n", get_reference_time() - t);
|
||||
}
|
||||
}
|
||||
|
||||
void save_value(unsigned char *path, unsigned char value)
|
||||
{
|
||||
//uint32_t t = get_reference_time();
|
||||
if (lfs_init() == 0)
|
||||
{
|
||||
lfs_write_config(path, (unsigned char*) &value, sizeof(value));
|
||||
}
|
||||
|
||||
lfs_deinit();
|
||||
}
|
||||
|
||||
unsigned char load_value(unsigned char *path)
|
||||
{
|
||||
unsigned char value = 255;
|
||||
if (lfs_init() == 0)
|
||||
{
|
||||
lfs_read_config(path, (unsigned char*) &value, sizeof(value));
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_printf("lfs_init failed\n");
|
||||
}
|
||||
|
||||
lfs_deinit();
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
#if (NUM_USB_CHAN_OUT != 0) || (NUM_USB_CHAN_IN != 0)
|
||||
unsigned short XUA_Endpoint0_getProductId();
|
||||
unsigned short XUA_Endpoint0_getVendorId();
|
||||
void XUA_Endpoint0_setProductId(unsigned short pid);
|
||||
void XUA_Endpoint0_setVendorStr(char* vendor_str);
|
||||
void XUA_Endpoint0_setProductStr(char* product_str);
|
||||
void XUA_Endpoint0_setSerialStr(char* serial_str);
|
||||
void XUA_Endpoint0_setVendorId(unsigned short vid);
|
||||
|
||||
void get_pid_vid()
|
||||
{
|
||||
unsigned crc;
|
||||
if ((productInfo.vid1 != 0) || (productInfo.vid2 != 0)
|
||||
|| (productInfo.pid1 != 0 ) || (productInfo.pid2 != 0))
|
||||
{
|
||||
unsigned char tmp[17];
|
||||
crc = calculate_crc32((unsigned char *) &productInfo, sizeof(productInfo) - 4);
|
||||
|
||||
if (NTOHL(crc) == productInfo.crc || crc == productInfo.crc)
|
||||
{
|
||||
debug_printf("crc is correct\n");
|
||||
#if (AUDIO_CLASS == 1)
|
||||
{
|
||||
XUA_Endpoint0_setProductId(NTOHS(productInfo.pid1));
|
||||
XUA_Endpoint0_setVendorId(NTOHS(productInfo.vid1));
|
||||
debug_printf(" pid %04x vid %04x\n", NTOHS(productInfo.pid1), NTOHS(productInfo.vid1));
|
||||
}
|
||||
#else
|
||||
{
|
||||
XUA_Endpoint0_setProductId(NTOHS(productInfo.pid2));
|
||||
XUA_Endpoint0_setVendorId(NTOHS(productInfo.vid2));
|
||||
debug_printf(" pid %04x vid %04x\n", NTOHS(productInfo.pid2), NTOHS(productInfo.vid2));
|
||||
}
|
||||
#endif
|
||||
|
||||
memcpy (tmp, productInfo.ManufactureName, 16);
|
||||
tmp[16] = 0;
|
||||
XUA_Endpoint0_setVendorStr(tmp);
|
||||
|
||||
memcpy (tmp, productInfo.ProductName, 16);
|
||||
XUA_Endpoint0_setProductStr(tmp);
|
||||
|
||||
memcpy (tmp, productInfo.SerialNumber, 16);
|
||||
XUA_Endpoint0_setSerialStr(tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
debug_printf("crc error %08x actual %08x\n", NTOHL(crc), productInfo.crc);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
void fill_boot_cmd(unsigned char *buffer)
|
||||
{
|
||||
int count = 0;
|
||||
unsigned short vid, pid;
|
||||
|
||||
buffer[count++] = 0;
|
||||
if (productInfo.vid1 == 0 && productInfo.vid2 == 0
|
||||
&& productInfo.pid1 == 0 && productInfo.pid2 == 0)
|
||||
{
|
||||
|
||||
#if (NUM_USB_CHAN_OUT != 0) || (NUM_USB_CHAN_IN != 0)
|
||||
pid = XUA_Endpoint0_getProductId();
|
||||
vid = XUA_Endpoint0_getVendorId();
|
||||
|
||||
buffer[count++] = vid >> 8;
|
||||
buffer[count++] = vid & 0xff;
|
||||
buffer[count++] = pid >> 8;
|
||||
buffer[count++] = pid & 0xff;
|
||||
|
||||
buffer[count++] = vid >> 8;
|
||||
buffer[count++] = vid & 0xff;
|
||||
buffer[count++] = pid >> 8;
|
||||
buffer[count++] = pid & 0xff;
|
||||
|
||||
for(int i = 0; i < 8; i++)
|
||||
buffer[count++] = 0;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
buffer[count++] = productInfo.vid1 & 0xff;
|
||||
buffer[count++] = productInfo.vid1 >> 8;
|
||||
buffer[count++] = productInfo.pid1 & 0xff;
|
||||
buffer[count++] = productInfo.pid1 >> 8;
|
||||
|
||||
buffer[count++] = productInfo.vid2 & 0xff;
|
||||
buffer[count++] = productInfo.vid2 >> 8;
|
||||
buffer[count++] = productInfo.pid2 & 0xff;
|
||||
buffer[count++] = productInfo.pid2 >> 8;
|
||||
|
||||
buffer[count++] = productInfo.crc & 0xff;
|
||||
buffer[count++] = (productInfo.crc >> 8) & 0xff;
|
||||
buffer[count++] = (productInfo.crc >> 16) & 0xff;
|
||||
buffer[count++] = (productInfo.crc >> 24) & 0xff;
|
||||
|
||||
buffer[count++] = appPowerOnConf.crc & 0xff;
|
||||
buffer[count++] = (appPowerOnConf.crc >> 8) & 0xff;
|
||||
buffer[count++] = (appPowerOnConf.crc >> 16) & 0xff;
|
||||
buffer[count++] = (appPowerOnConf.crc >> 24) & 0xff;
|
||||
}
|
||||
|
||||
}
|
||||
void fill_finish_cmd(unsigned char *buffer)
|
||||
{
|
||||
memcpy(buffer, (unsigned char *)&appUserConf, sizeof(appUserConf));
|
||||
}
|
||||
|
||||
void save_product_info(unsigned char *buffer)
|
||||
{
|
||||
memcpy((unsigned char *)&productInfo, buffer, sizeof(productInfo));
|
||||
}
|
||||
|
||||
void save_powerup_info(unsigned char *buffer)
|
||||
{
|
||||
memcpy((unsigned char *)&appPowerOnConf, buffer, sizeof(appPowerOnConf));
|
||||
}
|
||||
|
||||
void save_userconfig_info(unsigned char *buffer)
|
||||
{
|
||||
memcpy((unsigned char *)&appUserConf, buffer, sizeof(appUserConf));
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
#ifndef _USER_FUNC_H_
|
||||
#define _USER_FUNC_H_
|
||||
|
||||
#include <xs1.h>
|
||||
#include <print.h>
|
||||
#include <platform.h>
|
||||
#include <xclib.h>
|
||||
#include <xscope.h>
|
||||
#include <assert.h>
|
||||
#include "user_uart.h"
|
||||
|
||||
// 32-bit macros for converting between host and network byte order
|
||||
#define HTONL(value) ( \
|
||||
(((value) >> 24) & 0x000000FF) | \
|
||||
(((value) >> 8) & 0x0000FF00) | \
|
||||
(((value) << 8) & 0x00FF0000) | \
|
||||
(((value) << 24) & 0xFF000000) \
|
||||
)
|
||||
|
||||
#define NTOHL(value) HTONL(value) // Since the transformation is the same
|
||||
|
||||
// 16-bit macros for converting between host and network byte order
|
||||
#define HTONS(value) ( \
|
||||
(((value) >> 8) & 0x00FF) | \
|
||||
(((value) << 8) & 0xFF00) \
|
||||
)
|
||||
|
||||
#define NTOHS(value) HTONS(value) // Since the transformation is the same
|
||||
|
||||
#ifdef __XC__
|
||||
uint32_t calculate_crc32(uint8_t *unsafe buf, int len);
|
||||
unsigned char check_sum(uint8_t *unsafe pbuf, unsigned len);
|
||||
void fill_boot_cmd(unsigned char *unsafe buffer);
|
||||
void save_product_info(unsigned char *unsafe buffer);
|
||||
void save_powerup_info(unsigned char *unsafe buffer);
|
||||
void fill_finish_cmd(unsigned char *unsafe buffer);
|
||||
void save_userconfig_info(unsigned char *unsafe buffer);
|
||||
#else
|
||||
uint32_t calculate_crc32(uint8_t *buf, int len);
|
||||
unsigned char check_sum(uint8_t *pbuf, unsigned len);
|
||||
void fill_boot_cmd(unsigned char *buffer);
|
||||
void save_product_info(unsigned char *buffer);
|
||||
void save_powerup_info(unsigned char *buffer);
|
||||
void fill_finish_cmd(unsigned char *buffer);
|
||||
void save_userconfig_info(unsigned char *buffer);
|
||||
#endif
|
||||
void load_configs(void);
|
||||
void save_configs(unsigned char save);
|
||||
void get_pid_vid();
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
|
||||
#ifndef _USER_MAIN_H_
|
||||
#define _USER_MAIN_H_
|
||||
|
||||
#ifdef __XC__
|
||||
|
||||
#include "i2c.h"
|
||||
#include <print.h>
|
||||
#include <xs1.h>
|
||||
#include <platform.h>
|
||||
#include "DSBuild.h"
|
||||
|
||||
//extern unsafe client interface i2c_master_if i_i2c_client;
|
||||
//extern unsafe client interface i2c_master_if i_i2c_client_t0;
|
||||
extern void interface_saver(client interface i2c_master_if i);
|
||||
extern void dsp_core0(void);
|
||||
extern void board_setup();
|
||||
extern void dsp_main (chanend c_data);
|
||||
extern void SetEqDataChan (chanend c);
|
||||
|
||||
/* I2C interface ports */
|
||||
extern port p_scl;
|
||||
extern port p_sda;
|
||||
|
||||
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);
|
||||
extern void AudioHwRemote(chanend c_hidSendData, chanend cc_mic_level, chanend c_uac_vol);
|
||||
extern void dnr_dsp_proc_task(void);
|
||||
|
||||
//XUA_DFU_EN do i need it?
|
||||
|
||||
// tile[0]
|
||||
// 3 DSP processors
|
||||
// XUD_Main
|
||||
// Core USB audio task, buffering, USB etc
|
||||
// Endpoint 0 Core
|
||||
// i2c_master
|
||||
// DFUHandler???
|
||||
|
||||
|
||||
//IAP??
|
||||
|
||||
//tile[1]:
|
||||
// ex3d
|
||||
// hid + buttons
|
||||
// 4 DSP processors
|
||||
// usb_audio_io
|
||||
//
|
||||
|
||||
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;
|
||||
extern void key_sender(chanend c_key);
|
||||
extern void key_receiver(chanend c_key);
|
||||
|
||||
#if AIZIP_DNR == 1
|
||||
#define USER_MAIN_DECLARATIONS \
|
||||
chan c_dsp_to_ex3d[DSP_WORKER_COUNT]; \
|
||||
chan cc_dsp_in; chan cc_dsp_eof; chan cc_mic_level; chan c;
|
||||
|
||||
#define USER_MAIN_CORES on tile[1]: {\
|
||||
par\
|
||||
{\
|
||||
ex3d_task();\
|
||||
par(int i=0;i<DSP_WORKER_COUNT;i++) dsp_worker_tile(c_dsp_to_ex3d[i], i);\
|
||||
unsafe\
|
||||
{\
|
||||
uc_audiohw = (chanend) c;\
|
||||
for(int i=0;i<DSP_WORKER_COUNT;i++)\
|
||||
uc_dsp_to_ex3d[i] = (chanend) c_dsp_to_ex3d[i];\
|
||||
uc_dsp_to_dnr_t1 = (chanend) cc_dsp_in;\
|
||||
}\
|
||||
hid_button_task(cc_mic_level, c_hid, c_hidSendData);\
|
||||
}\
|
||||
}\
|
||||
on tile[0]: {\
|
||||
par\
|
||||
{\
|
||||
unsafe\
|
||||
{\
|
||||
board_setup();\
|
||||
} \
|
||||
AudioHwRemote(c);\
|
||||
dnr_dsp_buffer_task(cc_dsp_in, cc_dsp_eof, cc_mic_level);\
|
||||
dnr_dsp_proc_task(cc_dsp_eof);\
|
||||
}\
|
||||
}
|
||||
#else
|
||||
|
||||
#define USER_MAIN_DECLARATIONS \
|
||||
chan c_dsp_to_ex3d[DSP_WORKER_COUNT]; chan cc_mic_level; chan c_key; chan c_hidSendData; chan c_hidRcvData; chan c_eq_data; chan c_uac_vol;
|
||||
|
||||
#define USER_MAIN_CORES on tile[1]: {\
|
||||
par\
|
||||
{\
|
||||
hid_button_task(cc_mic_level, c_hidRcvData, c_hidSendData, c_uac_vol);\
|
||||
par(int i=0;i<DSP_WORKER_COUNT;i++) dsp_worker_tile(c_dsp_to_ex3d[i], i);\
|
||||
unsafe\
|
||||
{\
|
||||
SetEqDataChan(c_eq_data); \
|
||||
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();\
|
||||
}\
|
||||
}\
|
||||
}\
|
||||
on tile[0]: {\
|
||||
par\
|
||||
{\
|
||||
{ \
|
||||
unsafe\
|
||||
{\
|
||||
key_receiver(c_key);\
|
||||
}\
|
||||
AudioHwRemote(c_hidSendData, cc_mic_level, c_uac_vol);\
|
||||
} \
|
||||
}\
|
||||
}\
|
||||
on tile[0]: {\
|
||||
{ dsp_core0(); } \
|
||||
}\
|
||||
on tile[0]: {dsp_main(c_eq_data); } \
|
||||
on tile[0]: {dnr_dsp_proc_task(); } \
|
||||
|
||||
|
||||
#endif // AIZIP_DNR
|
||||
|
||||
#endif // __XC__
|
||||
|
||||
#endif // _USER_MAIN_H_
|
||||
@@ -0,0 +1,263 @@
|
||||
#ifndef _UART_H_
|
||||
#define _UART_H_
|
||||
|
||||
#include <xs1.h>
|
||||
#include <platform.h>
|
||||
#include <xclib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef enum {
|
||||
AUDIO_PCM_44100 = 0,
|
||||
AUDIO_PCM_48000,
|
||||
AUDIO_PCM_88200,
|
||||
AUDIO_PCM_96000,
|
||||
AUDIO_PCM_176400,
|
||||
AUDIO_PCM_192000,
|
||||
AUDIO_PCM_352800,
|
||||
AUDIO_PCM_384000,
|
||||
AUDIO_PCM_705600,
|
||||
AUDIO_PCM_768000,
|
||||
AUDIO_PCM_1441200,
|
||||
AUDIO_PCM_1536000,
|
||||
|
||||
AUDIO_PCM_32000,
|
||||
AUDIO_PCM_64000,
|
||||
AUDIO_PCM_128000,
|
||||
AUDIO_PCM_256000,
|
||||
AUDIO_PCM_512000,
|
||||
|
||||
AUDIO_DSD_64,
|
||||
AUDIO_DSD_128,
|
||||
AUDIO_DSD_256,
|
||||
AUDIO_DSD_512,
|
||||
AUDIO_DSD_1024,
|
||||
|
||||
AUDIO_MQA_44100,
|
||||
AUDIO_MQA_88200,
|
||||
AUDIO_MQA_176400,
|
||||
AUDIO_MQA_352800,
|
||||
AUDIO_MQA_705600,
|
||||
AUDIO_MQA_1411200,
|
||||
AUDIO_MQA_2822400,
|
||||
AUDIO_MQA_5644800,
|
||||
|
||||
AUDIO_MQA_48000,
|
||||
AUDIO_MQA_96000,
|
||||
AUDIO_MQA_192000,
|
||||
AUDIO_MQA_384000,
|
||||
AUDIO_MQA_768000,
|
||||
AUDIO_MQA_1536000,
|
||||
AUDIO_MQA_3072000,
|
||||
AUDIO_MQA_6144000,
|
||||
|
||||
AUDIO_MQA_64000,
|
||||
AUDIO_MQA_128000,
|
||||
AUDIO_MQA_256000,
|
||||
AUDIO_MQA_512000,
|
||||
AUDIO_MQA_1024000,
|
||||
AUDIO_MQA_2048000,
|
||||
AUDIO_MQA_4096000,
|
||||
AUDIO_MQA_8192000,
|
||||
|
||||
AUDIO_NO_USED = 0xFF,
|
||||
} audio_sampling;
|
||||
|
||||
typedef enum {
|
||||
PCM = 0, /**< PCM */
|
||||
Reserve = 1, /**< Reserved */
|
||||
MQA = 2, /**< MQA */
|
||||
MQB = 3, /**< MQB */
|
||||
MQA_Studio = 4, /**< MQA Studio */
|
||||
DSD = 5, /**< DSD Native*/
|
||||
} audio_type;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
USER_CMD_VOL_UP = 0x00,
|
||||
USER_CMD_VOL_DOWN,
|
||||
USER_CMD_PLAY,
|
||||
USER_CMD_NEXT,
|
||||
USER_CMD_PREV,
|
||||
USER_CMD_FORWARD,
|
||||
USER_CMD_REWIND,
|
||||
USER_CMD_MUTE
|
||||
} ButtonEvent;
|
||||
|
||||
typedef enum {
|
||||
AUDIO_FREQ_44100 = 0,
|
||||
AUDIO_FREQ_48000,
|
||||
AUDIO_FREQ_88200,
|
||||
AUDIO_FREQ_96000,
|
||||
AUDIO_FREQ_176400,
|
||||
AUDIO_FREQ_192000,
|
||||
AUDIO_FREQ_352800,
|
||||
AUDIO_FREQ_384000,
|
||||
AUDIO_FREQ_705600,
|
||||
AUDIO_FREQ_768000,
|
||||
AUDIO_FREQ_1411200,
|
||||
AUDIO_FREQ_1536000
|
||||
} AudioFreq;
|
||||
|
||||
typedef enum {
|
||||
AUDIO_CLASS_UAC1 = 0,
|
||||
AUDIO_CLASS_UAC2
|
||||
} AudioClass;
|
||||
|
||||
typedef enum {
|
||||
AUDIO_WIDTH_16BIT = 0,
|
||||
AUDIO_WIDTH_24BIT = 1,
|
||||
AUDIO_WIDTH_32BIT = 2
|
||||
} AudioWidth;
|
||||
|
||||
typedef enum {
|
||||
MODE_USB = 0,
|
||||
MODE_OPT,
|
||||
MODE_COAX,
|
||||
MODE_BT,
|
||||
MODE_HDMI_ARC,
|
||||
MODE_WIFI,
|
||||
MODE_AIRPLAY,
|
||||
MODE_SPOTIFY
|
||||
} UserMode;
|
||||
|
||||
typedef enum {
|
||||
START_BOOT = 0,
|
||||
READ_PRODUCT = 1,
|
||||
READ_POR_CONFIG = 2,
|
||||
READ_AUDIO_MODE = 3,
|
||||
READ_USER_CONFIG = 4,
|
||||
START_FINISH = 5,
|
||||
REPORT_APP_STATUS = 0x20,
|
||||
MEDIA_CONTROL = 0x21,
|
||||
SEND_AUDIO_FORMAT = 0x22,
|
||||
SWITCH_AUDIO_MODE = 0x23,
|
||||
SEND_OUT_VOLUME = 0x24,
|
||||
SEND_IN_VOLUME = 0x25,
|
||||
SET_DAC_VOLUME = 0x26,
|
||||
SET_DAC_MODE = 0x27,
|
||||
SET_DAC_M_GAIN = 0x32,
|
||||
TEST_CMD = 0xF0,
|
||||
FW_VERSION = 0xF1,
|
||||
FLASH_ID = 0xF2,
|
||||
// EQ命令定义 (0x40-0x5C)
|
||||
SET_EQ_MODE = 0x40, // 切换EQ模式
|
||||
GET_EQ_MODE = 0x41, // 获取当前EQ模式信息
|
||||
SET_MODE_GAIN_AND_NAME = 0x42, // 设置模式整体增益和名称
|
||||
SET_EQ_PARAMS = 0x43, // 发送EQ参数
|
||||
GET_EQ_PARAMS = 0x44, // 读取EQ参数
|
||||
GET_DEVICE_INFO = 0x45, // 获取设备信息
|
||||
RESET_EQ_PARAMS = 0x46, // 复位EQ参数
|
||||
GET_EQ_MODE_COUNT = 0x47, // 获取EQ模式总数
|
||||
SET_AND_SAVE_EQ_MODE = 0x48, // 设置并保存EQ模式
|
||||
SET_VOLUME = 0x49, // 设置音量级别
|
||||
GET_VOLUME = 0x4A, // 获取音量级别
|
||||
GET_LED_INFO = 0x4B, // 获取LED信息
|
||||
SET_LED_SWITCH = 0x4C, // 设置LED开关
|
||||
GET_LED_SWITCH = 0x4D, // 获取LED开关
|
||||
GET_LED_STATUS = 0x4E, // 获取LED状态
|
||||
GET_LED_COUNT = 0x4F, // 获取LED总数
|
||||
GET_UAC_MODE_INFO = 0x50, // 获取UAC模式信息
|
||||
SET_UAC_MODE = 0x51, // 设置UAC模式
|
||||
GET_CURRENT_UAC_MODE = 0x52, // 获取当前UAC模式
|
||||
SET_EQ_ENABLE = 0x53, // 设置EQ使能开关
|
||||
GET_EQ_ENABLE = 0x54, // 获取EQ使能开关
|
||||
GET_SAMPLE_FORMAT = 0x55, // 获取采样率和格式
|
||||
SET_GAIN_MODE = 0x56, // 设置增益模式
|
||||
GET_GAIN_MODE = 0x57, // 获取增益模式
|
||||
SET_FILTER_MODE = 0x58, // 设置滤波器模式
|
||||
GET_FILTER_MODE = 0x59, // 获取滤波器模式
|
||||
SET_GAME_MODE = 0x5A, // 设置游戏模式
|
||||
GET_GAME_MODE = 0x5B, // 获取游戏模式
|
||||
GET_FIRMWARE_VERSION = 0x5C, // 获取固件版本
|
||||
CMD_NONE = 0xFF
|
||||
} UartCmdType;
|
||||
|
||||
#define CMD_HEAD1_POS 0
|
||||
#define CMD_HEAD2_POS 1
|
||||
#define CMD_VERSION_POS 2
|
||||
#define CMD_CMD_POS 3
|
||||
#define CMD_DATA_LEN_POS 4
|
||||
#define CMD_DATA_POS 5
|
||||
|
||||
#define BOOT_CMD_DATA_LEN 17
|
||||
#define FINISH_CMD_DATA_LEN 15
|
||||
#define PRODUCT_CMD_DATA_LEN 61
|
||||
#define CONFIG_CMD_DATA_LEN 14
|
||||
#define AUDIO_MODE_CMD_DATA_LEN 5
|
||||
|
||||
#define UART_HEAD1 0x55
|
||||
#define UART_HEAD2 0xAA
|
||||
#define UART_HEAD 0x55
|
||||
#define UART_HEAD_LEN 0x05
|
||||
|
||||
#if !__XC__
|
||||
typedef struct {
|
||||
uint8_t I2S_Mode : 1; // I2S Mode: 0 - Master, 1 - Slave
|
||||
uint8_t Sync_Mode : 1; // Sync Mode: 0 - Async, 1 - Sync
|
||||
uint8_t MIDI_Enable : 1; // MIDI Enable: 0 - Disable, 1 - Enable
|
||||
uint8_t SPDIF_In : 1; // SPDIF Input: 0 - Disable, 1 - Enable
|
||||
uint8_t SPDIF_Out : 1; // SPDIF Output: 0 - Disable, 1 - Enable
|
||||
uint8_t ADAT_In : 1; // ADAT Input: 0 - Disable, 1 - Enable
|
||||
uint8_t ADAT_Out : 1; // ADAT Output: 0 - Disable, 1 - Enable
|
||||
uint8_t DSD_Out : 1; // DSD Output: 0 - Disable, 1 - Enable
|
||||
|
||||
uint8_t Audio_Sample_Rate : 4; // Audio Sample Rate
|
||||
uint8_t MQA_Enable : 1; // MQA Enable: 0 - Disable, 1 - Enable
|
||||
uint8_t Audio_Class : 1; // Audio Class: 0 - UAC 1.0, 1 - USB UAC 2.0
|
||||
uint8_t Audio_Width : 2; // Audio Width: 0 - 16bit, 1 - 24bit, 2 - 32bit
|
||||
|
||||
uint16_t Input_Channel : 6; // Input Channel Count
|
||||
uint16_t Output_Channel : 6; // Output Channel Count
|
||||
uint16_t Other_Cfg : 4; // Other Configuration
|
||||
|
||||
UserMode Mode; // Mode
|
||||
} AudioMode;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint16_t vid1;
|
||||
uint16_t pid1;
|
||||
uint16_t vid2;
|
||||
uint16_t pid2;
|
||||
uint8_t ManufactureName[16];
|
||||
uint8_t ProductName[16];
|
||||
uint8_t SerialNumber[16];
|
||||
uint32_t crc;
|
||||
} ProductInfo;
|
||||
|
||||
typedef struct {
|
||||
AudioMode audioMode;
|
||||
uint16_t muteTime;
|
||||
uint8_t micVol;
|
||||
uint8_t dacLvol;
|
||||
uint8_t dacRvol;
|
||||
uint32_t crc;
|
||||
} AppConfigs;
|
||||
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
USB_MODE = 1 ,
|
||||
OPT_MODE ,
|
||||
COAX_MODE ,
|
||||
BT_MODE ,
|
||||
HDMI_ARC_MODE ,
|
||||
WIFI_MODE ,
|
||||
AIRPLAY_MODE ,
|
||||
SPOTIFY_MODE ,
|
||||
} UsbMode;
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
unsigned char startFlag;
|
||||
unsigned char startConfig;
|
||||
unsigned char startApp;
|
||||
unsigned char cmdCount;
|
||||
unsigned char cmdPending;
|
||||
unsigned char pendingReboot;
|
||||
} UserCmdConfig;
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user