📄 dtv_ref4_audio.c
字号:
/*******************************************************/
extern tmLibdevErr_t dtvRef4_AO_Start_1(void)
{
aoEnableTRANS_ENABLEM(AO1_STATUS);
return TMLIBDEV_OK;
}
/*******************************************************/
extern tmLibdevErr_t dtvRef4_AO_Stop_1(void)
{
aoDisableTRANS_ENABLEM(AO1_STATUS);
return TMLIBDEV_OK;
}
/***********************************************************************
* Convert a floating point sample rate value
* to a 32 bit frequency control value for the DDS.
*
* NOTE: YOU MUST SET THE sckdiv, wsdiv and sfdiv FIELDS FOR THIS TO WORK!
*
* Accurate to .5 ppm.
* The DDS can do better than this, but 64 bit math is
* required to use this interface.
*/
extern tmLibdevErr_t dtvRef4_AO_SetSRate_1(Float sRate)
{
UInt ao_serial;
Float sckdiv, wsdiv, val;
ao_serial = MMIO(AO1_SERIAL);
sckdiv = (Float) (aoExtractSCKDIV(ao_serial) + 1);
wsdiv = (Float) (aoExtractWSDIV(ao_serial) + 1);
sRate = sRate * sckdiv * wsdiv;
val = 0.5 + (477218588.0 * (sRate / dtvRef4CPUClock)); /* 2**32 / 9 */
aoSetFREQM(AO1_STATUS, ((UInt) val) | 0x80000000);
return TMLIBDEV_OK;
}
/*******************************************************/
extern tmLibdevErr_t dtvRef4_AO_GetSRate_1(Float * sRate)
{
UInt serial = MMIO(AO1_SERIAL);
UInt freq = MMIO(AO1_FREQ);
UInt sckdiv = 1 + aoExtractSCKDIV(serial);
UInt wsdiv = 1 + aoExtractWSDIV(serial);
Float rate;
rate = (Float) (freq & 0x7fffffff) * dtvRef4CPUClock / 477218588.0;
rate = rate / ((Float) sckdiv * (Float) wsdiv);
*sRate = rate;
return TMLIBDEV_OK;
}
/*******************************************************/
extern tmLibdevErr_t dtvRef4_AO_Config_1(UInt32 subaddr, Pointer value)
{
return AIO_ERR_COMMAND_NOT_SUPPORTED;
}
/*******************************************************/
extern tmLibdevErr_t dtvRef4_AO_Init_2(boardAOParam_t * param)
{
Float val;
pprocCapabilities_t procCap;
Int err = TMLIBDEV_OK;
/* get the clock frequency of the TriMedia CPU */
err = procGetCapabilities(&procCap);
if (err) return err;
dtvRef4CPUClock = (Float) procCap->cpuClockFrequency;
/* reset the audio output peripheral */
aoRESETM(AO2_STATUS);
/* Set initial frequency to get AO into a stable state */
val = param->sRate * 256.0; /* 256 * sampleRate */
val = 0.5 + (477218588.0 * (val / dtvRef4CPUClock)); /* 2**32 / 9 */
aoSetFREQM(AO2_STATUS, ((UInt) val) | 0x80000000);
aoEnableSER_MASTERM(AO2_STATUS);
microsleep(10); /* wait until AO unit stabalized */
if (! (param->audioTypeFormat & DTV_REF4_SUPPORTED_AUDIO_OUT_TYPES_2) )
return AIO_ERR_UNSUPPORTED_FORMAT;
if (! (param->audioSubtypeFormat & DTV_REF4_SUPPORTED_AUDIO_OUT_SUBTYPES_2) )
return AIO_ERR_UNSUPPORTED_FORMAT;
/* enable LCLK 1-4 to enable L3 clocks for HD DACs */
err = xioRegWriteBit(0x00, 0x10, False);
err |= xioRegWriteBit(0x00, 0x20, False);
if (err != TMLIBDEV_OK)
{
aoRESETM(AO2_STATUS);
return err;
}
/* initialize the DACs (UDA 1320) */
err = uda13xxInitOutput(&sdUdaParam, &sdUdaOutputParam);
if (err != TMLIBDEV_OK)
{
aoRESETM(AO2_STATUS);
return err;
}
/* disable LCLK 1-4 to enable L3 clocks for HD DACs */
err = xioRegWriteBit(0x00, 0x10, True);
err |= xioRegWriteBit(0x00, 0x20, True);
if (err != TMLIBDEV_OK)
{
aoRESETM(AO2_STATUS);
return err;
}
#ifdef __LITTLE_ENDIAN__
aoEnableLITTLE_ENDIANM(AO2_STATUS);
#else
aoDisableLITTLE_ENDIANM(AO2_STATUS);
#endif
aoMsbFirstM(AO2_STATUS);
aoStartRisingEdgeWSM(AO2_STATUS);
aoSampleRisingCLOCK_EDGEM(AO2_STATUS); /* sample on rising edge */
aoSetSSPOSM(AO2_STATUS, 0); /* Left and right channel start at bit 0 */
aoDisableSIGN_CONVERTM(AO2_STATUS); /* Disable Sign Convert for MSB */
aoDisableWS_PULSEM(AO2_STATUS); /* word strobe in pulse mode */
aoDisableTRANS_ENABLEM(AO2_STATUS);
switch (param->audioSubtypeFormat) {
case apfStereo16: /* Two channel Audio */
{ /* 64 * 4 * 1 = 256fs */
DP(("AO2 stereo 16 bit\n"));
aoSetTRANS_MODEM(AO2_STATUS, 3);
aoSetWSDIVM(AO2_STATUS, 63);
aoSetSCKDIVM(AO2_STATUS, 3);
aoSetNR_CHANM(AO2_STATUS, 0);
aoSetLEFTPOSM(AO2_STATUS, 0);
aoSetRIGHTPOSM(AO2_STATUS, 32);
aoSetSIZEM(AO2_STATUS, param->size);
break;
}
case apfStereo32: /* Two channel Audio, 32-bit */
{ /* 64 * 4 * 1 = 256 fs */
DP(("AO2 stereo 32 bit\n"));
aoSetTRANS_MODEM(AO2_STATUS, 1);
aoSetWSDIVM(AO2_STATUS, 63);
aoSetSCKDIVM(AO2_STATUS, 3);
aoSetNR_CHANM(AO2_STATUS, 0);
aoSetLEFTPOSM(AO2_STATUS, 0);
aoSetRIGHTPOSM(AO2_STATUS, 32);
aoSetSIZEM(AO2_STATUS, param->size);
break;
}
default:
/* unsupported subtype */
return(AIO_ERR_UNSUPPORTED_FORMAT);
}
/* set sample rate */
err = dtvRef4_AO_SetSRate_2(param->sRate);
return err;
} /* end of dtvRef4_AO_Init() */
/*******************************************************/
extern tmLibdevErr_t dtvRef4_AO_Term_2(void)
{
aoRESETM(AO2_STATUS);
return TMLIBDEV_OK;
}
/*******************************************************/
extern tmLibdevErr_t dtvRef4_AO_Start_2(void)
{
aoEnableTRANS_ENABLEM(AO2_STATUS);
return TMLIBDEV_OK;
}
/*******************************************************/
extern tmLibdevErr_t dtvRef4_AO_Stop_2(void)
{
aoDisableTRANS_ENABLEM(AO2_STATUS);
return TMLIBDEV_OK;
}
/***********************************************************************
* Convert a floating point sample rate value
* to a 32 bit frequency control value for the DDS.
*
* NOTE: YOU MUST SET THE sckdiv, wsdiv and sfdiv FIELDS FOR THIS TO WORK!
*
* Accurate to .5 ppm.
* The DDS can do better than this, but 64 bit math is
* required to use this interface.
*/
extern tmLibdevErr_t dtvRef4_AO_SetSRate_2(Float sRate)
{
UInt ao_serial;
Float sckdiv, wsdiv, val;
ao_serial = MMIO(AO2_SERIAL);
sckdiv = (Float) (aoExtractSCKDIV(ao_serial) + 1);
wsdiv = (Float) (aoExtractWSDIV(ao_serial) + 1);
sRate = sRate * sckdiv * wsdiv;
val = 0.5 + (477218588.0 * (sRate / dtvRef4CPUClock)); /* 2**32 / 9 */
aoSetFREQM(AO2_STATUS, ((UInt) val) | 0x80000000);
return TMLIBDEV_OK;
}
/*******************************************************/
extern tmLibdevErr_t dtvRef4_AO_GetSRate_2(Float * sRate)
{
UInt serial = MMIO(AO2_SERIAL);
UInt freq = MMIO(AO2_FREQ);
UInt sckdiv = 1 + aoExtractSCKDIV(serial);
UInt wsdiv = 1 + aoExtractWSDIV(serial);
Float rate;
rate = (Float) (freq & 0x7fffffff) * dtvRef4CPUClock / 477218588.0;
rate = rate / ((Float) sckdiv * (Float) wsdiv);
*sRate = rate;
return TMLIBDEV_OK;
}
/*******************************************************/
extern tmLibdevErr_t dtvRef4_AO_Config_2(UInt32 subaddr, Pointer value)
{
return AIO_ERR_COMMAND_NOT_SUPPORTED;
}
/* Functions for the S/PDIF output */
extern tmLibdevErr_t dtvRef4_SPDO_Init(boardSPDOParam_t * param)
{
pprocCapabilities_t procCap;
Int err = TMLIBDEV_OK;
/* get the clock frequency of the TriMedia CPU */
err = procGetCapabilities(&procCap);
if (err) return err;
dtvRef4CPUClock = (Float) procCap->cpuClockFrequency;
spdoRESETM(SPDO_STATUS);
if (! (param->audioTypeFormat & DTV_REF4_SUPPORTED_SPDO_TYPES) )
return AIO_ERR_UNSUPPORTED_FORMAT;
if (! (param->audioSubtypeFormat & DTV_REF4_SUPPORTED_SPDO_SUBTYPES) )
return AIO_ERR_UNSUPPORTED_FORMAT;
#ifdef __LITTLE_ENDIAN__
spdoEnableLITTLE_ENDIANM(SPDO_STATUS);
#else
spdoDisableLITTLE_ENDIANM(SPDO_STATUS);
#endif
spdoSetTRANS_MODEM(SPDO_STATUS, 0); /* S/PDIF mode */
spdoSetSIZEM(SPDO_STATUS, param->size);
err = dtvRef4_SPDO_SetSRate(param->sRate);
return err;
}
extern tmLibdevErr_t dtvRef4_SPDO_Term(void)
{
spdoRESETM(SPDO_STATUS);
return TMLIBDEV_OK;
}
extern tmLibdevErr_t dtvRef4_SPDO_Start(void)
{
spdoEnableTRANS_ENABLEM(SPDO_STATUS);
return TMLIBDEV_OK;
}
extern tmLibdevErr_t dtvRef4_SPDO_Stop(void)
{
spdoDisableTRANS_ENABLEM(SPDO_STATUS);
return TMLIBDEV_OK;
}
extern tmLibdevErr_t dtvRef4_SPDO_SetSRate(Float sRate)
{
sRate *= 128;
sRate = 0.5 + (477218588.0 * (sRate / dtvRef4CPUClock));
spdoSetFREQM(SPDO_STATUS, ((UInt) sRate) | 0x80000000);
return TMLIBDEV_OK;
}
extern tmLibdevErr_t dtvRef4_SPDO_GetSRate(Float * sRate)
{
UInt freq = MMIO(SPDO_FREQ);
Float rate;
rate = (Float) (freq & 0x7fffffff) * dtvRef4CPUClock / 477218588.0;
rate = rate / 128.0;
*sRate = rate;
return TMLIBDEV_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -