Open oliverjrose99 opened 4 years ago
I have fixed my issue and possibly revealed a bug. powering down the apll / plla before all of the config functions and then powering it up seems to have fixed it.
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#include "driver/i2s.h"
#include "driver/adc.h"
#include "soc/i2s_reg.h"
#include "soc/syscon_reg.h"
#include "soc/syscon_struct.h"
#include "soc/sens_reg.h"
#include "soc/sens_periph.h"
#include "soc/sens_struct.h"
#include "esp_log.h"
#define SAMPLES 1024
#define SAMPLING_FREQ 44100
static const char* TAG = "MAIN";
void init_i2s_adc()
{
i2s_config_t i2s_config = {
.mode = I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN,
.sample_rate = 44100,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
.intr_alloc_flags = 0,
.dma_buf_count = 2,
.dma_buf_len = 1024,
.use_apll = 1,
};
// powerdown APLL/PLLA
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD_M);
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU_M);
// config adc atten and width
adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_11db);
adc1_config_width(ADC_WIDTH_12Bit);
// set pattern tbl and invert, might not need, double check
SYSCON.saradc_ctrl.sar1_patt_len = 1;
SYSCON.saradc_sar1_patt_tab[0] = 0b00001111000011110000111100001111;
SYSCON.saradc_ctrl2.sar1_inv = 1;
//install and start i2s driver
i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
i2s_set_adc_mode(I2S_NUM_0, ADC1_CHANNEL_0);
// delay and enable
vTaskDelay(3000 / portTICK_RATE_MS);
i2s_adc_enable(I2S_NUM_0);
// powerup APLL/PLLA
SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU_M);
CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD_M);
}
void app_main()
{
init_i2s_adc();
int read_len = 1024 * 2;
uint16_t* read_buff = (uint16_t*) calloc(read_len, sizeof(uint16_t));
size_t bytes_read;
while(1) {
i2s_read(I2S_NUM_0, (void*) read_buff, read_len, &bytes_read, portMAX_DELAY);
for (int i = 0; i < 64; i++) {
printf("%hu ", read_buff[i]);
if (i % 8 == 0) printf("\n");
}
}
}
I had same issue, with output to another i2s channel: apll does produce zeros values. This is fixed by install sar adr driver last over initializing i2s out (first). This work well without patch above (but, i'm think that is helpfull too). Keep in mind, that sar i2c input will come with first values of dma vector filled with acdual adc values, then last will be a noised values. Another words, in 1024 values single channel adc will produce [0..511] adc values and [512..1023] some randoms, so for listening it needs "interlace" with normal stereo i2s values.
I'm think that is very serious issue because with no apll adc produce some audible aliasing artifacts.
-- V.V.
Environment
Problem Description
When
use_apll = true
in the i2s config,i2s_read()
only returns 0s. Whenuse_apll = false
, the returned data is correct but the rate (as reported by the serial monitor) is not. I am trying to sample a 3.5mm audio jack (with the correct circuit) so a sample rate of 44.1kH is required.Note: sample rate requested is double as the real rate reported is half, this code is not mine and is mostly taken from phonec
My guess to fix this is that the apll clock need to be routed to the ADC by setting a register but but i cant find anything and dont know if that is correct. Please help, ive spent so long on this.
Code to reproduce this issue
Debug Logs
I havent included all of the boot log, i can add it if needed.
use_apll = true
use_apll = false