Page 1 of 1

Cosine generator frequency setting gives unexpected results

Posted: Wed Jun 07, 2023 7:57 pm
by oldndumb

Code: Select all

void start_sine_tone() {
    
    dac_i2s_disable();

    dac_cw_config_t cw_config = {
        .en_ch = AUDIO_OUT_PIN,
        .scale = DAC_CW_SCALE_4, //quietest is 8, loudest is 1
        .phase = DAC_CW_PHASE_0, //other option is DAC_CW_PHASE_180
        .freq = 500, //Results in a tone of around 390 Hz??
        .offset = 64 //rather strange that by default this parameter expects a range of -128 to 127, but the dac_output_voltage function expects 0 to 255 if I'm not mistaken?
    };

    // Configure DAC continuous wave generator
    dac_cw_generator_config(&cw_config);

    // Enable DAC continuous wave generator
    dac_cw_generator_enable();
}
Setting up this simple function to use the built-in cosine generator, I encounter a strange problem setting the frequency value. All values between roughly 350 and 500 result in a tone of around 390 Hz. Only setting it as high as 525 I get a much higher tone that's close to 525hz actually. Setting it to 300 I get a lower tone of about 260hz. What's the catch here? Why can I output only a certain frequencies? What is the math behind these frequency steps and what can I do about it? I would like to output a tone of 425Hz ideally.

EDIT: I am using ESP-IDF v4.4.4

Re: Cosine generator frequency setting gives unexpected results

Posted: Thu Jun 08, 2023 4:55 pm
by oldndumb
Dug up the Technical Reference Manual and found at least a clue:
Image
Image
Image
https://www.espressif.com/sites/default ... ual_en.pdf

Re: Cosine generator frequency setting gives unexpected results

Posted: Thu Jun 08, 2023 5:23 pm
by oldndumb
So if the frequency of dig_clk_rtc_freq is 8 MHz. We get the following:
freq = dig_clk_rtc_freq x SENS_SAR_SW_FSTEP / 65536
freq = 8000000 x SENS_SAR_SW_FSTEP / 65536
freq = ~122.07 x SENS_SAR_SW_FSTEP
frequency_step = 425 / ~122.07 = ~3.4816

We can set the frequecy by writing our calculated value to SENS_SAR_SW_FSTEP[15:0] field in SENS_SAR_DAC_CTRL1_REG register.
SET_PERI_REG_BITS(SENS_SAR_DAC_CTRL1_REG, SENS_SW_FSTEP, frequency_step, SENS_SW_FSTEP_S);

However I think it only takes full integer steps:
3 x 122 = 366
4 x 122 = 488

And the actual output frequency depends on the calibration of your boards clock etc. Which may explain the values I got out of mine.

If we can apply a prescaler / divider to the clock we might get closer to our desired frequency but need to read further to understand how to do that exactly. If you have some experience with it, please chime in.

Re: Cosine generator frequency setting gives unexpected results

Posted: Thu Jun 08, 2023 8:28 pm
by oldndumb

Code: Select all

uint8_t prescaler = 6; 
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, prescaler);
Comes closest on my board, with a frequency result of ~427.
This is only because my board I think is about 23Hz too high. But I'd have to confirm that by testing on different boards and I'll leave that up to future readers. For now I'm pretty happy with 427Hz...
--Cheers

Re: Cosine generator frequency setting gives unexpected results

Posted: Fri Jun 09, 2023 12:15 am
by corz.org