Skip to content

Commit

Permalink
Enabled 32bit ADC/DAC sample transfers
Browse files Browse the repository at this point in the history
We now run the codec(s) with their full data width (24bits)
(transfer size 32bit I2S data). Purpose is to have a little more margin
if your frontend does not deliver high enough IQ levels. It may or may
not improve the reception. It has almost no effect on performance since
we, as before, run most of the processing with floating point math.
A little extra work is on the DMA and SAI hardware (transfer amount doubled.
And a little conversion is necessary for now.

On platforms with 2 codecs you can select AUDIO and IQ bit width (16/32)
in any combination, on single codec devices (mcHF)
both have to be identical.

On STM32F4 we have an ugly hack to fix our inability to get proper 32bit via
DMA. The current approach is required for a working solution
as we have issues when working on the DMA buffers directly for swapping (we have to fix the
MPU config for that to work, I guess)

RAM usage grows by 0.5 (mcHF) to 1k (OVI40).
USB I/O still uses only 16bits (also for IQ data).
Audio driver load does not increase measurably.
  • Loading branch information
db4ple committed Jan 4, 2019
1 parent a56eabe commit 628cd2d
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 49 deletions.
4 changes: 2 additions & 2 deletions mchf-eclipse/.cproject
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="fw-mchf" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="${cross_rm} -rf" description="mcHF Firmware (STM32F4), requires DebugLibMCHF build to run before." errorParsers="org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.433341838" name="DebugMCHF" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug" postannouncebuildStep="" postbuildStep="${cross_prefix}${cross_objcopy}${cross_suffix} -O binary ${BuildArtifactFileName} ${BuildArtifactFileBaseName}.bin" preannouncebuildStep="" prebuildStep="">
<configuration artifactName="fw-mchf" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="${cross_rm} -rf" description="mcHF Firmware (STM32F4), requires DebugLibMCHF build to run before." errorParsers="org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.433341838" name="DebugMCHF" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=" parent="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug" postannouncebuildStep="" postbuildStep="${cross_prefix}${cross_objcopy}${cross_suffix} -O binary ${BuildArtifactFileName} ${BuildArtifactFileBaseName}.bin" preannouncebuildStep="" prebuildStep="">
<folderInfo id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.433341838." name="/" resourcePath="">
<toolChain errorParsers="" id="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.debug.680557654" name="Cross ARM GCC" nonInternalBuilderId="ilg.gnuarmeclipse.managedbuild.cross.builder" superClass="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.debug">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.384915231" name="Optimization Level" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.more" valueType="enumerated"/>
Expand Down Expand Up @@ -3372,7 +3372,7 @@
</extensions>
</storageModule>
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="fw-ovi40" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="${cross_rm} -rf" description="OVI40H7 Firmware (STM32H7), requires DebugLibOVI40H7 build to run before." errorParsers="org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.433341838.1123244320.487780019" name="DebugOVI40H7" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=" parent="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug" postannouncebuildStep="" postbuildStep="${cross_prefix}${cross_objcopy}${cross_suffix} -O binary ${BuildArtifactFileName} ${BuildArtifactFileBaseName}.bin" preannouncebuildStep="" prebuildStep="">
<configuration artifactName="fw-ovi40" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="${cross_rm} -rf" description="OVI40H7 Firmware (STM32H7), requires DebugLibOVI40H7 build to run before." errorParsers="org.eclipse.cdt.core.GmakeErrorParser;org.eclipse.cdt.core.CWDLocator;org.eclipse.cdt.core.GCCErrorParser;org.eclipse.cdt.core.GASErrorParser;org.eclipse.cdt.core.GLDErrorParser" id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.433341838.1123244320.487780019" name="DebugOVI40H7" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=" parent="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug" postannouncebuildStep="" postbuildStep="${cross_prefix}${cross_objcopy}${cross_suffix} -O binary ${BuildArtifactFileName} ${BuildArtifactFileBaseName}.bin" preannouncebuildStep="" prebuildStep="">
<folderInfo id="ilg.gnuarmeclipse.managedbuild.cross.config.elf.debug.433341838.1123244320.487780019." name="/" resourcePath="">
<toolChain errorParsers="" id="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.debug.1750162806" name="Cross ARM GCC" nonInternalBuilderId="ilg.gnuarmeclipse.managedbuild.cross.builder" superClass="ilg.gnuarmeclipse.managedbuild.cross.toolchain.elf.debug">
<option id="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.1609734234" name="Optimization Level" superClass="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level" useByScannerDiscovery="true" value="ilg.gnuarmeclipse.managedbuild.cross.option.optimization.level.debug" valueType="enumerated"/>
Expand Down
95 changes: 77 additions & 18 deletions mchf-eclipse/drivers/audio/audio_driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -710,7 +710,6 @@ void AudioDriver_LeakyLmsNr (float32_t *in_buff, float32_t *out_buff, int buff_s

void AudioDriver_Init(void)
{
const uint32_t word_size = WORD_SIZE_16;

// CW module init
CwGen_Init();
Expand Down Expand Up @@ -773,7 +772,7 @@ void AudioDriver_Init(void)
#endif


ts.codec_present = Codec_Reset(ts.samp_rate,word_size) == HAL_OK;
ts.codec_present = Codec_Reset(ts.samp_rate) == HAL_OK;

// Start DMA transfers
UhsdrHwI2s_Codec_StartDMA();
Expand Down Expand Up @@ -3511,6 +3510,44 @@ void AudioDriver_RxProcessorNoiseReduction(uint16_t blockSizeDecim, float32_t* i
}


// FIXME: This is ugly: The STM32F4 returns 32bit reads from 16 bit peripherals such as the SPI/I2S
// with the two half words in "mixed endian" instead of the wanted "little endian". This is documented in
// the data sheet, so the only thing we can do is to swap the halfwords. This is in fact a single ror16 operation
// if the compiler is smart enough to detect what we want.

// we have to swap them only if we are having 32bit values from/to I2S and an STM32F4
#if defined(STM32F4) && defined(USE_32_IQ_BITS)
static inline int32_t correctHalfWord(const int32_t word)
{
uint32_t uWord = (uint32_t)word;
return uWord >> 16 | uWord << 16;
}
#else
#define correctHalfWord(a) (a)
#endif

// these constants are used to adjust the 32 bit integer samples to represent the same levels as if we sample 16 bit integers,
// effectively "shifting" them down or up.
// FIXME: switch to 16 bit extended mode for 16 bit samples will eliminate the need for this at the expense of
// using the same DMA memory (two times the memory true 16 bit values take, in our case this is 2*(2*(IQ_BLOCK_SIZE*2samples*2bytes) = 512 bytes)
#ifdef USE_32_IQ_BITS
#define IQ_BIT_SHIFT 16
#define IQ_BIT_SCALE_DOWN (0.0000152587890625)
#else
#define IQ_BIT_SHIFT 0
#define IQ_BIT_SCALE_DOWN (1.0)
#endif
#define IQ_BIT_SCALE_UP (1<<IQ_BIT_SHIFT)

#ifdef USE_32_AUDIO_BITS
#define AUDIO_BIT_SHIFT 16
#define AUDIO_BIT_SCALE_DOWN (0.0000152587890625)
#else
#define AUDIO_BIT_SHIFT 0
#define AUDIO_BIT_SCALE_DOWN (1.0)
#endif
#define AUDIO_BIT_SCALE_UP (1<<AUDIO_BIT_SHIFT)

//
//*----------------------------------------------------------------------------
//* Function Name : audio_rx_processor
Expand Down Expand Up @@ -3544,37 +3581,41 @@ static void AudioDriver_RxProcessor(IqSample_t * const src, AudioSample_t * cons
{
// 16 bit format - convert to float and increment
// we collect our I/Q samples for USB transmission if TX_AUDIO_DIGIQ
audio_in_put_buffer(src[i].l);
audio_in_put_buffer(src[i].r);
audio_in_put_buffer(correctHalfWord(src[i].l)>>IQ_BIT_SHIFT);
audio_in_put_buffer(correctHalfWord(src[i].r)>>IQ_BIT_SHIFT);
}
}

if (ads.af_disabled == 0 )
{
// AudioDriver_NoiseBlanker(src, blockSize); // do noise blanker function
// ------------------------
// Split stereo channels
for(uint32_t i = 0; i < blockSize; i++)
{
if(src[i].l > ADC_CLIP_WARN_THRESHOLD/4) // This is the release threshold for the auto RF gain
int32_t level = abs(correctHalfWord(src[i].l))>>IQ_BIT_SHIFT;

if(level > ADC_CLIP_WARN_THRESHOLD/4) // This is the release threshold for the auto RF gain
{
ads.adc_quarter_clip = 1;
if(src[i].l > ADC_CLIP_WARN_THRESHOLD/2) // This is the trigger threshold for the auto RF gain
if(level > ADC_CLIP_WARN_THRESHOLD/2) // This is the trigger threshold for the auto RF gain
{
ads.adc_half_clip = 1;
if(src[i].l > ADC_CLIP_WARN_THRESHOLD) // This is the threshold for the red clip indicator on S-meter
if(level > ADC_CLIP_WARN_THRESHOLD) // This is the threshold for the red clip indicator on S-meter
{
ads.adc_clip = 1;
}
}
}
adb.i_buffer[i] = (float32_t)src[i].l;
adb.q_buffer[i] = (float32_t)src[i].r;
}

// artificial amplitude imbalance for testing of the automatic IQ imbalance correction
// arm_scale_f32 (adb.i_buffer, 0.6, adb.i_buffer, blockSize);
adb.i_buffer[i] = correctHalfWord(src[i].l);
adb.q_buffer[i] = correctHalfWord(src[i].r);
}

if (IQ_BIT_SCALE_DOWN != 1.0)
{
arm_scale_f32 (adb.i_buffer, IQ_BIT_SCALE_DOWN, adb.i_buffer, blockSize);
arm_scale_f32 (adb.q_buffer, IQ_BIT_SCALE_DOWN, adb.q_buffer, blockSize);
}

AudioDriver_RxHandleIqCorrection(blockSize);

Expand Down Expand Up @@ -3608,7 +3649,8 @@ static void AudioDriver_RxProcessor(IqSample_t * const src, AudioSample_t * cons
&& dmod_mode != DEMOD_FM
&& dmod_mode != DEMOD_SAM
&& dmod_mode != DEMOD_AM;
volatile const uint16_t blockSizeIQ = use_decimatedIQ? blockSizeDecim: blockSize;

const uint16_t blockSizeIQ = use_decimatedIQ? blockSizeDecim: blockSize;

// ------------------------
// In SSB and CW - Do 0-90 degree Phase-added Hilbert Transform
Expand Down Expand Up @@ -3986,6 +4028,17 @@ static void AudioDriver_RxProcessor(IqSample_t * const src, AudioSample_t * cons
{
dst[i].l = adb.a_buffer[1][i];
dst[i].r = adb.a_buffer[0][i];

// in case we have to scale up our values from 16 to 32 bit range. Yes, we don't use the lower bits from the float
// but that probably does not make a difference and this way it is faster.
// the halfword correction is required when we are running on a STM32F4 with 32bit IQ, which at the moment (!) implies a AUDIO_BIT_SHIFT
// so we are safe FOR NOW! When we adjust everything to 32bit, the correction has to remain but can be moved to the float to int conversion

if (AUDIO_BIT_SHIFT != 0)
{
dst[i].l = correctHalfWord(dst[i].l << AUDIO_BIT_SHIFT);
dst[i].r = correctHalfWord(dst[i].r << AUDIO_BIT_SHIFT);
}
}

// Unless this is DIGITAL I/Q Mode, we sent processed audio
Expand Down Expand Up @@ -4100,6 +4153,10 @@ static void AudioDriver_TxIqProcessingFinal(float32_t scaling, bool swap, IqSamp
{
int16_t trans_idx;

scaling *= IQ_BIT_SCALE_UP;
// this aligns resulting signal with 16 or 32 bit width integer MSB, see comment in
// the first part of AudioDriver_RxProcessor

if (ts.dmod_mode == DEMOD_CW || ts.iq_freq_mode == FREQ_IQ_CONV_MODE_OFF)
{
trans_idx = IQ_TRANS_OFF;
Expand Down Expand Up @@ -4135,8 +4192,8 @@ static void AudioDriver_TxIqProcessingFinal(float32_t scaling, bool swap, IqSamp
for(int i = 0; i < blockSize; i++)
{
// Prepare data for DAC
dst[i].l = final_i_buffer[i]; // save left channel
dst[i].r = final_q_buffer[i]; // save right channel
dst[i].l = correctHalfWord((int32_t)final_i_buffer[i]); // save left channel
dst[i].r = correctHalfWord((int32_t)final_q_buffer[i]); // save right channel
}

}
Expand Down Expand Up @@ -4192,18 +4249,20 @@ static void AudioDriver_TxAudioBufferFill(AudioSample_t * const src, int16_t blo
}
}

gain_calc *= AUDIO_BIT_SCALE_DOWN;

if(tx_audio_source == TX_AUDIO_LINEIN_R) // Are we in LINE IN RIGHT CHANNEL mode?
{
// audio buffer with right sample channel
for(int i = 0; i < blockSize; i++)
{
adb.a_buffer[0][i] = src[i].r;
adb.a_buffer[0][i] = correctHalfWord(src[i].r);
}
} else {
// audio buffer with left sample channel
for(int i = 0; i < blockSize; i++)
{
adb.a_buffer[0][i] = src[i].l;
adb.a_buffer[0][i] = correctHalfWord(src[i].l);
}
}

Expand Down
12 changes: 7 additions & 5 deletions mchf-eclipse/drivers/audio/audio_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,24 @@
#include "uhsdr_board.h"
//#include "audio_convolution.h"

// 16 or 24 bits from Codec
// 24 bits are not supported anywhere in the recent code!
//#define USE_24_BITS

#define IQ_SAMPLE_RATE (48000)
#define IQ_SAMPLE_RATE_F ((float32_t)IQ_SAMPLE_RATE)
//const float32_t IQ_SAMPLE_RATE_F = ((float32_t)IQ_SAMPLE_RATE);

typedef int16_t audio_data_t;

#ifdef USE_24_BITS
#if defined(USE_32_IQ_BITS)
typedef int32_t iq_data_t;
#else
typedef int16_t iq_data_t;
#endif

#if defined(USE_32_AUDIO_BITS)
typedef int32_t audio_data_t;
#else
typedef int16_t audio_data_t;
#endif


typedef struct {
__packed audio_data_t l;
Expand Down
51 changes: 41 additions & 10 deletions mchf-eclipse/drivers/audio/codec/codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@
#define W8731_ANLG_AU_PATH_CNTR_MICBBOOST (0x01)
#define W8731_DIGI_AU_INTF_FORMAT_PHILIPS 0x02
#define W8731_DIGI_AU_INTF_FORMAT_PCM 0x00
#define W8731_DIGI_AU_INTF_FORMAT_16B (0x00 << 2)
#define W8731_DIGI_AU_INTF_FORMAT_20B (0x01 << 2)
#define W8731_DIGI_AU_INTF_FORMAT_24B (0x10 << 2)
#define W8731_DIGI_AU_INTF_FORMAT_32B (0x11 << 2)
#define W8731_DIGI_AU_INTF_FORMAT_16B (0x0 << 2)
#define W8731_DIGI_AU_INTF_FORMAT_20B (0x1 << 2)
#define W8731_DIGI_AU_INTF_FORMAT_24B (0x2 << 2)
#define W8731_DIGI_AU_INTF_FORMAT_32B (0x3 << 2)

#define W8731_DIGI_AU_INTF_FORMAT_I2S_PROTO W8731_DIGI_AU_INTF_FORMAT_PHILIPS

Expand Down Expand Up @@ -89,7 +89,24 @@ typedef struct

__IO mchf_codec_t mchf_codecs[CODEC_NUM];

// FIXME: for now we use 32bits transfer size, does not change the ADC/DAC resolution
// which is 24 bits in any case. We should reduce finally to 24bits (which requires also the I2S/SAI peripheral to
// use 24bits)

#if defined(USE_32_IQ_BITS)
#define IQ_WORD_SIZE WORD_SIZE_32
#else
#define IQ_WORD_SIZE WORD_SIZE_16
#endif

#if defined(USE_32_AUDIO_BITS)
#define AUDIO_WORD_SIZE WORD_SIZE_32
#else
#define AUDIO_WORD_SIZE WORD_SIZE_16
#endif

#ifdef UI_BRD_OVI40

/**
* @brief controls volume on "external" PA via DAC
* @param vol volume in range of 0 to CODEC_SPEAKER_MAX_VOLUME
Expand Down Expand Up @@ -127,7 +144,7 @@ static uint32_t Codec_WriteRegister(I2C_HandleTypeDef* hi2c, uint8_t RegisterAdd
return MCHF_I2C_WriteRegister(hi2c, CODEC_ADDRESS, Byte1, 1, Byte2);
}

static uint32_t Codec_ResetCodec(I2C_HandleTypeDef* hi2c, uint32_t AudioFreq,uint32_t word_size)
static uint32_t Codec_ResetCodec(I2C_HandleTypeDef* hi2c, uint32_t AudioFreq, CodecSampleWidth_t word_size)
{
uint32_t retval = HAL_OK;

Expand Down Expand Up @@ -166,7 +183,21 @@ static uint32_t Codec_ResetCodec(I2C_HandleTypeDef* hi2c, uint32_t AudioFreq,uin


// Reg 07: Digital Audio Interface Format (i2s, 16/32 bit, slave)
uint16_t size_reg_val = word_size == WORD_SIZE_16? W8731_DIGI_AU_INTF_FORMAT_16B : W8731_DIGI_AU_INTF_FORMAT_32B;
uint16_t size_reg_val;

switch(word_size)
{
case WORD_SIZE_32:
size_reg_val = W8731_DIGI_AU_INTF_FORMAT_32B;
break;
case WORD_SIZE_24:
size_reg_val = W8731_DIGI_AU_INTF_FORMAT_24B;
break;
case WORD_SIZE_16:
default:
size_reg_val = W8731_DIGI_AU_INTF_FORMAT_16B;
break;
}

Codec_WriteRegister(hi2c, W8731_DIGI_AU_INTF_FORMAT,W8731_DIGI_AU_INTF_FORMAT_I2S_PROTO|size_reg_val);

Expand Down Expand Up @@ -204,18 +235,18 @@ static uint32_t Codec_ResetCodec(I2C_HandleTypeDef* hi2c, uint32_t AudioFreq,uin
* @param AudioFreq sample rate in Hertz
* @param word_size should be set to WORD_SIZE_16, since we have not yet implemented any other word_size
*/
uint32_t Codec_Reset(uint32_t AudioFreq,uint32_t word_size)
uint32_t Codec_Reset(uint32_t AudioFreq)
{

uint32_t retval;
#ifdef UI_BRD_MCHF
retval = Codec_ResetCodec(CODEC_I2C, AudioFreq,word_size);
retval = Codec_ResetCodec(CODEC_I2C, AudioFreq, IQ_WORD_SIZE);
#else
retval = Codec_ResetCodec(CODEC_ANA_I2C, AudioFreq,word_size);
retval = Codec_ResetCodec(CODEC_ANA_I2C, AudioFreq, AUDIO_WORD_SIZE);
if (retval == 0)
{
mchf_codecs[1].present = true;
retval = Codec_ResetCodec(CODEC_IQ_I2C, AudioFreq,word_size);
retval = Codec_ResetCodec(CODEC_IQ_I2C, AudioFreq, IQ_WORD_SIZE);
}
#endif
if (retval == 0)
Expand Down
10 changes: 7 additions & 3 deletions mchf-eclipse/drivers/audio/codec/codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,12 @@
#ifndef __CODEC_H
#define __CODEC_H

#define WORD_SIZE_16 0
#define WORD_SIZE_32 1
typedef enum
{
WORD_SIZE_16 = 0,
WORD_SIZE_24 = 2,
WORD_SIZE_32 = 3,
} CodecSampleWidth_t;

#include "ui_configuration.h"
#ifdef UI_BRD_MCHF
Expand All @@ -40,7 +44,7 @@ void Codec_LineInGainAdj(uint8_t gain);
void Codec_IQInGainAdj(uint8_t gain);
void Codec_MuteDAC(bool state);

uint32_t Codec_Reset(uint32_t AudioFreq,uint32_t word_size);
uint32_t Codec_Reset(uint32_t AudioFreq);
void Codec_RestartI2S();
void Codec_TxSidetoneSetgain(uint8_t mode);
void Codec_SwitchMicTxRxMode(uint8_t mode);
Expand Down
Loading

0 comments on commit 628cd2d

Please sign in to comment.