AD1938: what is the formula to transform the data received from AD1938 into volts?

I want to display a sine wave signal in a software program that I apply to the analog audio input of the codec. I get the data in the receive buffer, then convert it from a fixed-point format to a 32-bit floating-point format, but I do not know how to convert this data into an effective signal (amplitude in volts). Thank you.

  • 0
    •  Analog Employees 
    on Jun 23, 2017 7:18 PM

    Hello,

    The full-scale differential input for the AD1938 is listed as 1.9Vrms. To convert from digital amplitude to a voltage representation, you should just need to normalize a 100% FS signal to 1.9Vrms displayed in your software.

    Regards,

    Tyler

  • 0
    •  Analog Employees 
    on Jun 23, 2017 7:35 PM

    Hello Jerca,

    First you have to realize that it is just a number, it does not represent anything real outside of the digital world. First we have to assign some sort of standard to what full-scale is. The DAC is what assigns what the voltage will be. So a full scale number will produce a full scale voltage out of the DAC. In the case of the AD1938 the full scale voltage is 0.88V rms or 2.48Vp-p. Then you can divide this by the number of possible values, 2^24, to get the voltage of a single bit. So the same digital number will produce a different voltage out of different DACs depending on their internal reference.  

    For a 24 bit number that is in 2's compliment form,  the max number will be 0x7FF in hex for a positive number and 0x800 for a maximum negative number. Now this does not mean that the DAC will produce a negative voltage. Some do but many do not. Many DACs, the AD1938 included, have outputs raised up to a common mode voltage. This voltage will be the voltage of a zero in the data. So send out a 000 to the AD1938 and you will get 1.5V out of the DAC. A positive number into the DAC will produce a more positive voltage than 1.5V and a negative number sent to the DAC will produce a DC level less than 1.5V but never less than zero. Actually, I don't think it will be able to reach zero.

    So if you need to output DC out of the converter, you will need to reference the external Op-amps to the common mode voltage then translate it to what is required for the application.

    The same applies to the ADC side of things. Just as Tyler explained.

    I hope this helps.

    Dave T

  • So I use this configuration for AD1938:

    /* Setup the SPI parameters here in a buffer first */
    unsigned char ConfigParam1938[] = {
    (AD1938_ADDR),    CLKCTRL0,       DIS_ADC_DAC | INPUT256 | PLL_IN_MCLK | MCLK_OUT_OFF |                                                            PLL_PWR_DWN,
    (AD1938_ADDR),    CLKCTRL1,       DAC_CLK_PLL | ADC_CLK_PLL | DIS_VREF,
    (AD1938_ADDR),    DACCTRL0,       DAC_FMT_TDM | DAC_BCLK_DLY_1 | DAC_SR_48K,

    (AD1938_ADDR),    DACCTRL1,       DAC_LRCLK_POL_INV | DAC_BCLK_POL_INV | DAC_CHANNELS_8 |                                                                              DAC_LATCH_MID | DAC_BCLK_MASTER | DAC_LRCLK_MASTER,
    (AD1938_ADDR),    DACCTRL2,      DAC_WIDTH_24 | DAC_DEEMPH_32K,
    (AD1938_ADDR),    DACVOL_L1,    DACVOL_BEARABLE, /* Slot 4, Vout 1. */
    (AD1938_ADDR),    DACVOL_R1,   DACVOL_BEARABLE, /* Slot 5, Vout 5. */
    (AD1938_ADDR),    DACVOL_L2,    DACVOL_BEARABLE, /* Slot 6, Vout 2. */
    (AD1938_ADDR),    DACVOL_R2,    DACVOL_BEARABLE, /* Slot 7, Vout 6. */
    (AD1938_ADDR),    DACVOL_L3,    DACVOL_BEARABLE, /* Slot 0, Vout 3. */
    (AD1938_ADDR),    DACVOL_R3,   DACVOL_BEARABLE, /* Slot 1, Vout 7. */
    (AD1938_ADDR),    DACVOL_L4,    DACVOL_BEARABLE, /* Slot 2, Vout 4. */
    (AD1938_ADDR),    DACVOL_R4,    DACVOL_BEARABLE, /* Slot 3, Vout 8. */
    (AD1938_ADDR),    ADCCTRL0,       ADC_SR_48K,

    (AD1938_ADDR),    ADCCTRL1,       ADC_LATCH_MID | ADC_FMT_AUX | ADC_BCLK_DLY_1 | ADC_WIDTH_24,
    (AD1938_ADDR),    ADCCTRL2,       ADC_LRCLK_FMT_PULSE | ADC_BCLK_SLAVE | ADC_LRCLK_SLAVE |                                                            ADC_BCLK_SRC_INTERNAL | ADC_LRCLK_POL_INV | ADC_BCLK_POL_INV |                                                             ADC_CHANNELS_8,

    (AD1938_ADDR),    CLKCTRL0,       DIS_ADC_DAC | PLL_IN_MCLK | MCLK_OUT_OFF | INPUT256 | PLL_PWR_UP,
    (AD1938_ADDR),    CLKCTRL0,       ENA_ADC_DAC | PLL_IN_MCLK | MCLK_OUT_OFF | INPUT256 | PLL_PWR_UP,
    };

    and in my firmware I use a falling edge interrupt on the TDM_FS (SPORT 2 for transmision SPORT 3 for reception).

    In the interrupt I change the ping-pong buffer then I undersample the signal (the sample rate of codec is 32 KHz and I want 1 KHz):

    if(g_analog_input_cntr == 32)
    {
       g_analog_input_buffer[g_analog_input_state.sample_cntr_in] = g_analog_input_state.chL_mean / (float)0x20;
       g_analog_input_buffer[g_analog_input_state.sample_cntr_in + ANALOG_INPUT_CHANNEL_BUFFER_SIZE] =

                                              g_analog_input_state.chR_mean / (float)0x20;
       g_analog_input_state.chL_mean = 0;
       g_analog_input_state.chR_mean = 0;

       g_analog_input_cntr = 0;
       g_analog_input_state.sample_cntr_in = (g_analog_input_state.sample_cntr_in + 1) & ANALOG_INPUT_BUFFER_MASK;
    }
    else
    {
       g_analog_input_state.chL_mean += (float)(*(rx_block_pointer[buffer_cntr]) << 8) / (float)(0x7FFFFFFF);
       g_analog_input_state.chR_mean += (float)(*(rx_block_pointer[buffer_cntr] + 1) << 8) / (float)(0x7FFFFFFF);

       //g_analog_input_state.chL_mean += __builtin_conv_RtoF(*(rx_block_pointer[buffer_cntr]));
       //g_analog_input_state.chR_mean += __builtin_conv_RtoF(*(rx_block_pointer[buffer_cntr] + 1));

       g_analog_input_cntr++;
    }

    I want to transform the float values resulted from the fixed-point to floating-point conversion to amplitude values from the input sine wave. 

    What should I use for fixed-point to floating-point conversion? The __builtin_conv_RtoF() function or (float)(*(rx_block_pointer[buffer_cntr]) << 8) / (float)(0x7FFFFFFF)? Also, I use only IN1L and IN1R inputs so I should read only the first 2 slots of the rx buffer?

  • I just realised that the ADCs reads the output of DACs. If I send data to AD1938 (TDM_IN) I will recive the same data at TDM_OUT. In my system I use the DACs to send a signal from the MPU to the analog outputs and the ADCs to send to the MPU the signal from the analog inputs.

  • 0
    •  Analog Employees 
    on Jun 30, 2017 11:48 PM

    Hello Jerca,

    Something is wrong... You are setting the format of the ADC into the AUX mode. This will set it up for using external ADCs and DACs and the data pins change functions in the AUX modes.

    Look at table 13, Pin Function Changes in TDM and AUX modes and you will see the issue.

    You need to set the ADC in TDM mode if you are using only one codec. Even if you are using two codecs you would be daisy chaining them and not using the AUX modes.

    Regarding the code for setting up the serial ports and converting the numbers, you should ask that on the SHARC or BLACKFIN space on this forum since they can help answer those questions.