197 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			197 lines
		
	
	
		
			5.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include "SRC.h"
 | 
						|
 | 
						|
#define SRC_RATE        48000U
 | 
						|
#define reg(n) DSP->base + n
 | 
						|
 | 
						|
 | 
						|
int SRCInit ( DEV_STRUCT * DSP )
 | 
						|
{
 | 
						|
    u32_t   i;
 | 
						|
    int     retVal;
 | 
						|
 | 
						|
    /* Clear all SRC RAM then init - keep SRC disabled until done */
 | 
						|
    if (WaitBitd (reg(CONC_dSRCIO_OFF), SRC_BUSY_BIT, 0, 1000))
 | 
						|
        return (SRC_ERR_NOT_BUSY_TIMEOUT);
 | 
						|
 | 
						|
    pci_outl(reg(CONC_dSRCIO_OFF), SRC_DISABLE);
 | 
						|
 | 
						|
    for( i = 0; i < 0x80; ++i )
 | 
						|
        if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, (u16_t)i, 0U)))
 | 
						|
            return (retVal);
 | 
						|
 | 
						|
    if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_SYNTH_BASE + SRC_TRUNC_N_OFF, 16 << 4)))
 | 
						|
        return (retVal);
 | 
						|
    if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_SYNTH_BASE + SRC_INT_REGS_OFF, 16 << 10)))
 | 
						|
        return (retVal);
 | 
						|
    if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_DAC_BASE + SRC_TRUNC_N_OFF, 16 << 4)))
 | 
						|
        return (retVal);
 | 
						|
    if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_DAC_BASE + SRC_INT_REGS_OFF, 16 << 10)))
 | 
						|
        return (retVal);
 | 
						|
    if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_SYNTH_LVOL, 1 << 12)))
 | 
						|
        return (retVal);
 | 
						|
    if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_SYNTH_RVOL, 1 << 12)))
 | 
						|
        return (retVal);
 | 
						|
    if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_DAC_LVOL, 1 << 12)))
 | 
						|
        return (retVal);
 | 
						|
    if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_DAC_RVOL, 1 << 12)))
 | 
						|
        return (retVal);
 | 
						|
    if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_ADC_LVOL, 1 << 12)))
 | 
						|
        return (retVal);
 | 
						|
    if (SRC_SUCCESS != (retVal = SRCRegWrite(DSP, SRC_ADC_RVOL, 1 << 12)))
 | 
						|
        return (retVal);
 | 
						|
 | 
						|
    /* default some rates */
 | 
						|
    SRCSetRate(DSP, SRC_SYNTH_BASE, SRC_RATE);
 | 
						|
    SRCSetRate(DSP, SRC_DAC_BASE,   SRC_RATE);
 | 
						|
    SRCSetRate(DSP, SRC_ADC_BASE,   SRC_RATE);
 | 
						|
 | 
						|
    /* now enable the whole deal */
 | 
						|
    if (WaitBitd (reg(CONC_dSRCIO_OFF), SRC_BUSY_BIT, 0, 1000))
 | 
						|
        return (SRC_ERR_NOT_BUSY_TIMEOUT);
 | 
						|
 | 
						|
    pci_outl(reg(CONC_dSRCIO_OFF), 0UL);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int SRCRegRead(DEV_STRUCT * DSP, u16_t reg, u16_t *data)
 | 
						|
{
 | 
						|
    u32_t dtemp;
 | 
						|
 | 
						|
    /* wait for ready */
 | 
						|
    if (WaitBitd (reg(CONC_dSRCIO_OFF), SRC_BUSY_BIT, 0, 1000))
 | 
						|
        return (SRC_ERR_NOT_BUSY_TIMEOUT);
 | 
						|
 | 
						|
    dtemp = pci_inl(reg(CONC_dSRCIO_OFF));
 | 
						|
 | 
						|
    /* assert a read request */
 | 
						|
    pci_outl(reg(CONC_dSRCIO_OFF),
 | 
						|
            (dtemp & SRC_CTLMASK) | ((u32_t) reg << 25));
 | 
						|
 | 
						|
    /* now wait for the data */
 | 
						|
    if (WaitBitd (reg(CONC_dSRCIO_OFF), SRC_BUSY_BIT, 0, 1000))
 | 
						|
        return (SRC_ERR_NOT_BUSY_TIMEOUT);
 | 
						|
 | 
						|
    if (NULL != data)
 | 
						|
        *data = (u16_t) pci_inl(reg(CONC_dSRCIO_OFF));
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int SRCRegWrite(DEV_STRUCT * DSP, u16_t reg, u16_t val)
 | 
						|
{
 | 
						|
    u32_t dtemp;
 | 
						|
 | 
						|
 | 
						|
    /* wait for ready */
 | 
						|
    if (WaitBitd (reg(CONC_dSRCIO_OFF), SRC_BUSY_BIT, 0, 1000))
 | 
						|
        return (SRC_ERR_NOT_BUSY_TIMEOUT);
 | 
						|
 | 
						|
    dtemp = pci_inl(reg(CONC_dSRCIO_OFF));
 | 
						|
 | 
						|
    /* assert the write request */
 | 
						|
    pci_outl(reg(CONC_dSRCIO_OFF),
 | 
						|
            (dtemp & SRC_CTLMASK) | SRC_WENABLE | ((u32_t) reg << 25) | val);
 | 
						|
 | 
						|
    return 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void SRCSetRate(DEV_STRUCT * DSP, char base, u16_t rate)
 | 
						|
{
 | 
						|
  u32_t    freq, dtemp, i;
 | 
						|
  u16_t     N, truncM, truncStart, wtemp;
 | 
						|
 | 
						|
 | 
						|
  if( base != SRC_ADC_BASE )
 | 
						|
  {
 | 
						|
      /* freeze the channel */
 | 
						|
      dtemp = base == SRC_SYNTH_BASE ? SRC_SYNTHFREEZE : SRC_DACFREEZE;
 | 
						|
      for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
 | 
						|
          if( !(pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_BUSY) )
 | 
						|
              break;
 | 
						|
      pci_outl(reg(CONC_dSRCIO_OFF),
 | 
						|
              (pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_CTLMASK) |
 | 
						|
              dtemp);
 | 
						|
  
 | 
						|
      /* calculate new frequency and write it - preserve accum */
 | 
						|
      /* please don't try to understand. */
 | 
						|
      freq = ((u32_t) rate << 16) / 3000U;
 | 
						|
      SRCRegRead(DSP, base + SRC_INT_REGS_OFF, &wtemp);
 | 
						|
      
 | 
						|
      SRCRegWrite(DSP, base + SRC_INT_REGS_OFF,
 | 
						|
              (wtemp & 0x00ffU) |
 | 
						|
              (u16_t) (freq >> 6) & 0xfc00);
 | 
						|
              
 | 
						|
      SRCRegWrite(DSP, base + SRC_VFREQ_FRAC_OFF, (u16_t) freq >> 1);
 | 
						|
      
 | 
						|
      /* un-freeze the channel */
 | 
						|
      dtemp = base == SRC_SYNTH_BASE ? SRC_SYNTHFREEZE : SRC_DACFREEZE;
 | 
						|
      for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
 | 
						|
          if( !(pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_BUSY) )
 | 
						|
              break;
 | 
						|
      pci_outl(reg(CONC_dSRCIO_OFF),
 | 
						|
              (pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_CTLMASK) &
 | 
						|
              ~dtemp);
 | 
						|
  }
 | 
						|
  else /* setting ADC rate */
 | 
						|
  {
 | 
						|
    /* freeze the channel */
 | 
						|
    for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
 | 
						|
        if( !(pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_BUSY) )
 | 
						|
            break;
 | 
						|
    pci_outl(reg(CONC_dSRCIO_OFF),
 | 
						|
            (pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_CTLMASK) |
 | 
						|
            SRC_ADCFREEZE);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
    /* derive oversample ratio */
 | 
						|
    N = rate/3000U;
 | 
						|
    if( N == 15 || N == 13 || N == 11 || N == 9 )
 | 
						|
        --N;
 | 
						|
    SRCRegWrite(DSP, SRC_ADC_LVOL, N << 8);
 | 
						|
    SRCRegWrite(DSP, SRC_ADC_RVOL, N << 8);
 | 
						|
 | 
						|
    /* truncate the filter and write n/trunc_start */
 | 
						|
    truncM = (21*N - 1) | 1;
 | 
						|
    if( rate >= 24000U )
 | 
						|
    {
 | 
						|
        if( truncM > 239 )
 | 
						|
            truncM = 239;
 | 
						|
        truncStart = (239 - truncM) >> 1;
 | 
						|
        SRCRegWrite(DSP, base + SRC_TRUNC_N_OFF,
 | 
						|
                (truncStart << 9) | (N << 4));
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
        if( truncM > 119 )
 | 
						|
            truncM = 119;
 | 
						|
        truncStart = (119 - truncM) >> 1;
 | 
						|
        SRCRegWrite(DSP, base + SRC_TRUNC_N_OFF,
 | 
						|
                0x8000U | (truncStart << 9) | (N << 4));
 | 
						|
    }
 | 
						|
 | 
						|
    /* calculate new frequency and write it - preserve accum */
 | 
						|
    freq = ((48000UL << 16) / rate) * N;
 | 
						|
    SRCRegRead(DSP, base + SRC_INT_REGS_OFF, &wtemp);
 | 
						|
    SRCRegWrite(DSP, base + SRC_INT_REGS_OFF,
 | 
						|
            (wtemp & 0x00ffU) |
 | 
						|
            (u16_t) (freq >> 6) & 0xfc00);
 | 
						|
    SRCRegWrite(DSP, base + SRC_VFREQ_FRAC_OFF, (u16_t) freq >> 1);
 | 
						|
 | 
						|
    /* un-freeze the channel */
 | 
						|
    for( i = 0; i < SRC_IOPOLL_COUNT; ++i )
 | 
						|
        if( !(pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_BUSY) )
 | 
						|
            break;
 | 
						|
    pci_outl(reg(CONC_dSRCIO_OFF),
 | 
						|
            (pci_inl(reg(CONC_dSRCIO_OFF)) & SRC_CTLMASK) &
 | 
						|
            ~SRC_ADCFREEZE);
 | 
						|
  }
 | 
						|
  return;
 | 
						|
}
 | 
						|
 | 
						|
 |