Skip to content
This repository was archived by the owner on Jan 14, 2022. It is now read-only.
This repository was archived by the owner on Jan 14, 2022. It is now read-only.

Sample rate not ok? #3

@Xyp

Description

@Xyp

The function i2sSetRate in i2s_freertos.c did not work properly. When measuring the i2s wordselect frequency with then one, the function actually calculated (variable bestfreq), there was quite a deviation.
The accoustic effect was a change of sound-pitch.

The divider "calculation" in the below fix is not the most elegant one, but at least I think I identified the real formula for the word select formula (see code, line that begins with tstfreq=). The Base frequency is also 160 MHz (Independent on CPU speed setting).

Cannot commit the fix myself. So here the solution, which works for me.
Have also a second order sigma delta converter with over sampling ration of 64 working, delivering better sound quality (effectively 13.3 bit resolution, compared to 10 bits). E.g. speach does not sound that metallic anymore as before. Of course the noise on the IO pin itself will decrease the ENOB with respect to the ideal one.

So... here the sample rate fix code:

#define ABS(x) (((x)>0)?(x):(-(x)))

//Set the I2S sample rate, in HZ
void i2sSetRate(int rate) {
    //Find closest divider 
    int bestbck=0, bestfreq=0;
    int tstfreq;
    int i;
    int div;

    div = 2; // 2 is the minimal supported divider (divider 1 ends up in divider 2 setting)
    if (rate < 40000) // 39682 is the minimal sampling frequency supported with divider 2
        div = 3; // this one supports minimal 19841Hz

    //The base divider can be off by as much as <1 Compensate by trying to make the amount of bytes in the
    //i2s cycle more than 16. Do this by trying the amounts from 16 to 32 and keeping the one that fits best.
    for (i=1; i<64; i++) {
        tstfreq=(160000000l / (i*div*32) );
        printf("Best (%d,%d) cur (%d,%d) div %d\n", bestbck, bestfreq, i, tstfreq, ABS(rate-tstfreq));
        if (ABS(rate-tstfreq)<ABS(rate-bestfreq)) {
            bestbck=i;
            bestfreq=tstfreq;
        }
    }

    printf("ReqRate %d Div %d Bck %d Frq %d\n", rate, div, bestbck, bestfreq);
    CLEAR_PERI_REG_MASK(I2SCONF, I2S_TRANS_SLAVE_MOD|
                        (I2S_BITS_MOD<<I2S_BITS_MOD_S)|
                        (I2S_BCK_DIV_NUM <<I2S_BCK_DIV_NUM_S)|
                        (I2S_CLKM_DIV_NUM<<I2S_CLKM_DIV_NUM_S));
    SET_PERI_REG_MASK(I2SCONF, I2S_RIGHT_FIRST|I2S_MSB_RIGHT|I2S_RECE_SLAVE_MOD|
                        I2S_RECE_MSB_SHIFT|I2S_TRANS_MSB_SHIFT|
                        (((bestbck)&I2S_BCK_DIV_NUM )<<I2S_BCK_DIV_NUM_S)|
                        (((div)&I2S_CLKM_DIV_NUM)<<I2S_CLKM_DIV_NUM_S));
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions