- add sdkconfig for NO_SPIRAM and SPIRAM situation

- detect snapcast configuration and init everything accordingly, e.g sample rate, chunk duration, ...
  o calculate apll predefines in dependence of sample rate
  o communicate these settings to interested parties
- remove typos
This commit is contained in:
Carlos
2021-08-26 22:08:17 +02:00
Unverified
parent 15b4baba28
commit e799aaac25
13 changed files with 3471 additions and 190 deletions

View File

@@ -230,7 +230,7 @@ static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2
* @return ESP_ERR_INVALID_ARG or ESP_OK
*/
static esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir)
esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir)
{
int _odir, _sdm0, _sdm1, _sdm2;
float avg;

View File

@@ -202,6 +202,42 @@ esp_err_t i2s_custom_write_expand(i2s_port_t i2s_num, const void *src, size_t si
*/
esp_err_t i2s_custom_read(i2s_port_t i2s_num, void *dest, size_t size, size_t *bytes_read, TickType_t ticks_to_wait);
/**
* @brief APLL calculate function, was described by following:
* APLL Output frequency is given by the formula:
*
* apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2)
* apll_freq = fout / ((o_div + 2) * 2)
*
* The dividend in this expression should be in the range of 240 - 600 MHz.
* In rev. 0 of ESP32, sdm0 and sdm1 are unused and always set to 0.
* * sdm0 frequency adjustment parameter, 0..255
* * sdm1 frequency adjustment parameter, 0..255
* * sdm2 frequency adjustment parameter, 0..63
* * o_div frequency divider, 0..31
*
* The most accurate way to find the sdm0..2 and odir parameters is to loop through them all,
* then apply the above formula, finding the closest frequency to the desired one.
* But 256*256*64*32 = 134.217.728 loops are too slow with ESP32
* 1. We will choose the parameters with the highest level of change,
* With 350MHz<fout<500MHz, we limit the sdm2 from 4 to 9,
* Take average frequency close to the desired frequency, and select sdm2
* 2. Next, we look for sequences of less influential and more detailed parameters,
* also by taking the average of the largest and smallest frequencies closer to the desired frequency.
* 3. And finally, loop through all the most detailed of the parameters, finding the best desired frequency
*
* @param[in] rate The I2S Frequency (MCLK)
* @param[in] bits_per_sample The bits per sample
* @param[out] sdm0 The sdm 0
* @param[out] sdm1 The sdm 1
* @param[out] sdm2 The sdm 2
* @param[out] odir The odir
*
* @return ESP_ERR_INVALID_ARG or ESP_OK
*/
esp_err_t i2s_apll_calculate_fi2s(int rate, int bits_per_sample, int *sdm0, int *sdm1, int *sdm2, int *odir);
/**
* @brief Set sample rate used for I2S RX and TX.
*

View File

@@ -1,42 +1,18 @@
# Config file for ESP32 DSP Processor
menu "ESP32 audio buffer and I2S pin config"
menu "ESP32 audio buffer and I2S config"
config USE_PSRAM
bool "Use PSRAM"
default true
depends on ESP32_SPIRAM_SUPPORT
help
Need wrover class modules with large SPRAM to have required buffers for Snapcast network delay
Need wrover class modules with large SPRAM to have buffers >1s and chunks >20ms for Snapcast network delay
config USE_DSP_PROCESSOR
bool "enable signal processing on audio data"
default false
help
enable audio filtering before queueing it to player component
config BITS_PER_SAMPLE
int "bits per sample output to i2s driver"
default 16
help
Select number of bits per sample for codec configured and connected to esp32 i2s dma hw
config CHANNELS
int "number of channels per sample output to i2s driver"
default 2
help
Select number of channels per sample for codec configured and connected to esp32 i2s dma hw
config PCM_SAMPLE_RATE
int "sample rate of audio pcm data"
default 48000
help
sample rate of audio data, currently only 48kHz is heavily tested and used during development
config WIRE_CHUNK_DURATION_MS
int "wire chunk duration [ms]"
default 20
help
pcm data is encoded in chunks of x ms, this value has to match snapserver configuration
config USE_BIQUAD_ASM
bool "Use uptimized asm version of Biquad_f32"

View File

@@ -30,8 +30,8 @@
static const char *TAG = "dspProc";
static const uint8_t chunkDurationMs = CONFIG_WIRE_CHUNK_DURATION_MS;
static const uint32_t sampleRate = CONFIG_PCM_SAMPLE_RATE;
//static const uint8_t chunkDurationMs = CONFIG_WIRE_CHUNK_DURATION_MS;
//static const uint32_t sampleRate = CONFIG_PCM_SAMPLE_RATE;
//static const uint8_t channels = CONFIG_CHANNELS;
//static const uint8_t bitsPerSample = CONFIG_BITS_PER_SAMPLE;
@@ -48,6 +48,9 @@ static float *sbuftmp0 = NULL;//[1024];
extern uint8_t muteCH[4];
static uint32_t currentSamplerate = 0;
static uint32_t currentChunkDurationMs = 0;
ptype_t bq[8];
@@ -265,10 +268,18 @@ int dsp_processor(char *audio, size_t chunk_size, dspFlows_t dspFlow) {
// ----------------------------------------
// Fixed 2x2 biquad flow Xover for biAmp systems
// Interface for cross over frequency and level
void dsp_setup_flow(double freq, uint32_t samplerate) {
void dsp_setup_flow(double freq, uint32_t samplerate, uint32_t chunkDurationMs) {
float f = freq / samplerate / 2.0;
uint16_t len = (sampleRate * chunkDurationMs / 1000);
uint16_t len = (samplerate * chunkDurationMs / 1000);
if (((currentSamplerate == samplerate) && (currentChunkDurationMs == chunkDurationMs)) ||
(samplerate == 0) || (chunkDurationMs == 0))
{
return;
}
currentSamplerate = samplerate;
currentChunkDurationMs = chunkDurationMs;
bq[0] = (ptype_t){LPF, f, 0, 0.707, NULL, NULL, {0, 0, 0, 0, 0}, {0, 0}};
bq[1] = (ptype_t){LPF, f, 0, 0.707, NULL, NULL, {0, 0, 0, 0, 0}, {0, 0}};
@@ -279,11 +290,11 @@ void dsp_setup_flow(double freq, uint32_t samplerate) {
bq[6] = (ptype_t){LOWSHELF, f, 6, 0.707, NULL, NULL, {0, 0, 0, 0, 0}, {0, 0}};
bq[7] = (ptype_t){LOWSHELF, f, 6, 0.707, NULL, NULL, {0, 0, 0, 0, 0}, {0, 0}};
pnode_t *aflow = NULL;
aflow = malloc(sizeof(pnode_t));
if (aflow == NULL) {
printf("Could not create node");
}
// pnode_t *aflow = NULL;
// aflow = malloc(sizeof(pnode_t));
// if (aflow == NULL) {
// printf("Could not create node");
// }
for (uint8_t n = 0; n <= 7; n++) {
switch (bq[n].filtertype) {
@@ -306,6 +317,18 @@ void dsp_setup_flow(double freq, uint32_t samplerate) {
// printf("\n");
}
if (sbuffer0 != NULL) {
free(sbuffer0);
sbuffer0 = NULL;
}
if (sbufout0 != NULL) {
free(sbufout0);
sbufout0 = NULL;
}
if (sbuftmp0 != NULL) {
free(sbuftmp0);
sbuftmp0 = NULL;
}
sbuffer0 = (float *)heap_caps_malloc(sizeof(float) * len, MALLOC_CAP_8BIT);
sbufout0 = (float *)heap_caps_malloc(sizeof(float) * len, MALLOC_CAP_8BIT);

View File

@@ -39,7 +39,7 @@ typedef struct pnode {
struct pnode *next;
} pnode_t;
void dsp_setup_flow(double freq, uint32_t samplerate);
void dsp_setup_flow(double freq, uint32_t samplerate, uint32_t chunkDurationMs);
int dsp_processor(char *audio, size_t chunk_size, dspFlows_t dspFlow);
void dsp_set_xoverfreq(uint8_t, uint8_t, uint32_t);

View File

@@ -5,14 +5,7 @@
#include "esp_types.h"
#include "sdkconfig.h"
#include "snapcast.h"
// TODO: make the following configurable through menuconfig
// @ 48kHz, 2ch, 16bit audio data and 24ms wirechunks (hardcoded for now) we
// expect 0.024 * 2 * 16/8 * 48000 = 4608 Bytes
#define WIRE_CHUNK_DURATION_MS CONFIG_WIRE_CHUNK_DURATION_MS
#define SAMPLE_RATE CONFIG_PCM_SAMPLE_RATE
#define CHANNELS CONFIG_CHANNELS
#define BITS_PER_SAMPLE CONFIG_BITS_PER_SAMPLE
#include "i2s.h"
#define I2S_PORT I2S_NUM_0
@@ -34,6 +27,21 @@ typedef struct pcm_chunk_message {
pcm_chunk_fragment_t *fragment;
} pcm_chunk_message_t;
typedef enum codec_type_e { NONE, PCM, FLAC, OGG, OPUS } codec_type_t;
typedef struct snapcastSetting_s {
uint32_t buffer_ms;
uint32_t chunkDuration_ms;
codec_type_t codec;
int32_t sampleRate;
uint8_t channels;
i2s_bits_per_sample_t bits;
bool muted;
uint32_t volume;
} snapcastSetting_t;
QueueHandle_t init_player(void);
int deinit_player(void);
@@ -42,13 +50,11 @@ int8_t free_pcm_chunk(pcm_chunk_message_t *pcmChunk);
int8_t player_latency_insert(int64_t newValue);
int8_t player_notify_buffer_ms(uint32_t ms);
int8_t player_send_snapcast_setting(snapcastSetting_t setting);
int8_t reset_latency_buffer(void);
int8_t latency_buffer_full(void);
int8_t get_diff_to_server(int64_t *tDiff);
int8_t server_now(int64_t *sNow);
// void tg0_timer_init(void);
// void snapcast_sync_task(void *pvParameters);
#endif // __PLAYER_H__

View File

@@ -30,24 +30,14 @@
static const char *TAG = "PLAYER";
/**
* @brief Pre define APLL parameters, save compute time
* @brief Pre define APLL parameters, save compute time. They are calculated in player_setup_i2s()
* | bits_per_sample | rate | sdm0 | sdm1 | sdm2 | odir
*
* apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div +
* 2) * 2) I2S bit clock is (apll_freq / 16)
*/
static const int apll_predefine[][6] = {
{16, 11025, 38, 80, 5, 31}, {16, 16000, 147, 107, 5, 21},
{16, 22050, 130, 152, 5, 15}, {16, 32000, 129, 212, 5, 10},
{16, 44100, 15, 8, 5, 6}, {16, 48000, 136, 212, 5, 6},
{16, 96000, 143, 212, 5, 2}, {0, 0, 0, 0, 0, 0}};
static const int apll_predefine_48k_corr[][6] = {
{16, 48048, 27, 215, 5, 6}, // ~ 48kHz * 1.001
{16, 47952, 20, 210, 5, 6}, // ~ 48kHz * 0.999
{16, 48005, 213, 212, 5, 6}, // ~ 48kHz * 1.0001
{16, 47995, 84, 212, 5, 6}, // ~ 48kHz * 0.9999
};
static int apll_normal_predefine[6] = {0, 0, 0, 0, 0, 0};
static int apll_corr_predefine[][6] = {{0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}};
static SemaphoreHandle_t latencyBufSemaphoreHandle = NULL;
@@ -73,13 +63,15 @@ static uint8_t pcmChunkQueueStorageArea[PCM_CHNK_QUEUE_LENGTH *
static TaskHandle_t syncTaskHandle = NULL;
static const size_t chunkInBytes =
(WIRE_CHUNK_DURATION_MS * SAMPLE_RATE * CHANNELS * (BITS_PER_SAMPLE / 8)) /
1000;
static QueueHandle_t snapcastSettingQueueHandle = NULL;
static size_t chunkInBytes;
static uint32_t i2sDmaBufCnt;
static uint32_t i2sDmaBufMaxLen;
snapcastSetting_t currentSnapcastSetting;
static void tg0_timer_init(void);
static void tg0_timer_deinit(void);
static void snapcast_sync_task(void *pvParameters);
@@ -93,11 +85,15 @@ static void snapcast_sync_task(void *pvParameters);
#define CONFIG_SLAVE_I2S_DATAOUT_PIN 5
*/
static esp_err_t player_setup_i2s(uint32_t sample_rate, i2s_port_t i2sNum) {
int chunkInFrames = chunkInBytes / (CHANNELS * (BITS_PER_SAMPLE / 8));
static esp_err_t player_setup_i2s(i2s_port_t i2sNum, snapcastSetting_t *setting) {
int chunkInFrames;
int __dmaBufCnt;
int __dmaBufLen;
const int __dmaBufMaxLen = 1024;
int m_scale = 8, fi2s_clk;
chunkInBytes = (setting->chunkDuration_ms * setting->sampleRate * setting->channels * (setting->bits / 8)) / 1000;
chunkInFrames = chunkInBytes / (setting->channels * (setting->bits / 8));
__dmaBufCnt = 1;
__dmaBufLen = chunkInFrames;
@@ -116,13 +112,32 @@ static esp_err_t player_setup_i2s(uint32_t sample_rate, i2s_port_t i2sNum) {
i2sDmaBufCnt = __dmaBufCnt;
i2sDmaBufMaxLen = __dmaBufLen;
fi2s_clk = setting->sampleRate * setting->channels * setting->bits * m_scale;
apll_normal_predefine[0] = setting->bits;
apll_normal_predefine[1] = setting->sampleRate;
if (i2s_apll_calculate_fi2s(fi2s_clk, setting->bits, &apll_normal_predefine[2], &apll_normal_predefine[3], &apll_normal_predefine[4], &apll_normal_predefine[5]) != ESP_OK) {
ESP_LOGE(TAG, "ERROR, fi2s_clk");
}
apll_corr_predefine[0][0] = setting->bits;
apll_corr_predefine[0][1] = setting->sampleRate * 1.001;
if (i2s_apll_calculate_fi2s(fi2s_clk * 1.001, setting->bits, &apll_corr_predefine[0][2], &apll_corr_predefine[0][3], &apll_corr_predefine[0][4], &apll_corr_predefine[0][5]) != ESP_OK) {
ESP_LOGE(TAG, "ERROR, fi2s_clk * 1.001");
}
apll_corr_predefine[1][0] = setting->bits;
apll_corr_predefine[1][1] = setting->sampleRate * 0.999;
if (i2s_apll_calculate_fi2s(fi2s_clk * 0.999, setting->bits, &apll_corr_predefine[1][2], &apll_corr_predefine[1][3], &apll_corr_predefine[1][4], &apll_corr_predefine[1][5]) != ESP_OK) {
ESP_LOGE(TAG, "ERROR, fi2s_clk * 0.999");
}
ESP_LOGI(TAG, "player_setup_i2s: dma_buf_len is %d, dma_buf_count is %d",
i2sDmaBufMaxLen, i2sDmaBufCnt);
i2s_config_t i2s_config0 = {
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
.sample_rate = sample_rate,
.bits_per_sample = BITS_PER_SAMPLE,
.sample_rate = setting->sampleRate,
.bits_per_sample = setting->bits,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.dma_buf_count = i2sDmaBufCnt,
@@ -136,6 +151,7 @@ static esp_err_t player_setup_i2s(uint32_t sample_rate, i2s_port_t i2sNum) {
i2s_pin_config_t pin_config0;
get_i2s_pins(i2sNum, &pin_config0);
i2s_custom_driver_uninstall(i2sNum);
i2s_custom_driver_install(i2sNum, &i2s_config0, 0, NULL);
i2s_custom_set_pin(i2sNum, &pin_config0);
@@ -193,7 +209,16 @@ int deinit_player(void) {
QueueHandle_t init_player(void) {
int ret;
ret = player_setup_i2s(SAMPLE_RATE, I2S_PORT);
currentSnapcastSetting.buffer_ms = 1000;
currentSnapcastSetting.chunkDuration_ms = 20;
currentSnapcastSetting.codec = NONE;
currentSnapcastSetting.sampleRate = 44100;
currentSnapcastSetting.channels = 2;
currentSnapcastSetting.bits = 16;
currentSnapcastSetting.muted = false;
currentSnapcastSetting.volume = 70;
ret = player_setup_i2s(I2S_NUM_0, &currentSnapcastSetting);
if (ret < 0) {
ESP_LOGE(TAG, "player_setup_i2s failed: %d", ret);
@@ -265,6 +290,36 @@ int8_t player_notify_buffer_ms(uint32_t ms) {
return 0;
}
/**
*
*/
int8_t player_send_snapcast_setting(snapcastSetting_t setting) {
int ret;
if ((syncTaskHandle == NULL) || (snapcastSettingQueueHandle == NULL)) {
return -1;
}
if ((currentSnapcastSetting.bits != setting.bits) ||
(currentSnapcastSetting.buffer_ms != setting.buffer_ms) ||
(currentSnapcastSetting.channels != setting.channels) ||
(currentSnapcastSetting.chunkDuration_ms != setting.chunkDuration_ms) ||
(currentSnapcastSetting.codec != setting.codec) ||
(currentSnapcastSetting.muted != setting.muted) ||
(currentSnapcastSetting.sampleRate != setting.sampleRate) ||
(currentSnapcastSetting.volume != setting.volume))
{
// notify task of changed parameters
memcpy(&currentSnapcastSetting, &setting, sizeof(snapcastSetting_t));
ret = xQueueSend(snapcastSettingQueueHandle, &currentSnapcastSetting, pdMS_TO_TICKS(10));
if (ret != pdPASS) {
ESP_LOGE(TAG, "player_send_snapcast_setting: couldn't send snapcast setting");
}
}
return 0;
}
/**
*
*/
@@ -465,31 +520,53 @@ static void tg0_timer1_start(uint64_t alarm_value) {
// rate * (number of channels) * bits_per_sample
void adjust_apll(int8_t direction) {
int sdm0, sdm1, sdm2, o_div;
int index = 2; // 2 for slow adjustment, 0 for fast adjustment
// int index = 2; // 2 for slow adjustment, 0 for fast adjustment
// only change if necessary
if (currentDir == direction) {
return;
}
// if (direction == 1) {
// // speed up
// sdm0 = apll_predefine_48k_corr[index][2];
// sdm1 = apll_predefine_48k_corr[index][3];
// sdm2 = apll_predefine_48k_corr[index][4];
// o_div = apll_predefine_48k_corr[index][5];
// } else if (direction == -1) {
// // slow down
// sdm0 = apll_predefine_48k_corr[index + 1][2];
// sdm1 = apll_predefine_48k_corr[index + 1][3];
// sdm2 = apll_predefine_48k_corr[index + 1][4];
// o_div = apll_predefine_48k_corr[index + 1][5];
// } else {
// // reset to normal playback speed
// sdm0 = apll_predefine[5][2];
// sdm1 = apll_predefine[5][3];
// sdm2 = apll_predefine[5][4];
// o_div = apll_predefine[5][5];
//
// direction = 0;
// }
if (direction == 1) {
// speed up
sdm0 = apll_predefine_48k_corr[index][2];
sdm1 = apll_predefine_48k_corr[index][3];
sdm2 = apll_predefine_48k_corr[index][4];
o_div = apll_predefine_48k_corr[index][5];
sdm0 = apll_corr_predefine[0][2];
sdm1 = apll_corr_predefine[0][3];
sdm2 = apll_corr_predefine[0][4];
o_div = apll_corr_predefine[0][5];
} else if (direction == -1) {
// slow down
sdm0 = apll_predefine_48k_corr[index + 1][2];
sdm1 = apll_predefine_48k_corr[index + 1][3];
sdm2 = apll_predefine_48k_corr[index + 1][4];
o_div = apll_predefine_48k_corr[index + 1][5];
sdm0 = apll_corr_predefine[1][2];
sdm1 = apll_corr_predefine[1][3];
sdm2 = apll_corr_predefine[1][4];
o_div = apll_corr_predefine[1][5];
} else {
// reset to normal playback speed
sdm0 = apll_predefine[5][2];
sdm1 = apll_predefine[5][3];
sdm2 = apll_predefine[5][4];
o_div = apll_predefine[5][5];
sdm0 = apll_normal_predefine[2];
sdm1 = apll_normal_predefine[3];
sdm2 = apll_normal_predefine[4];
o_div = apll_normal_predefine[5];
direction = 0;
}
@@ -593,6 +670,28 @@ int8_t insert_pcm_chunk(wire_chunk_message_t *decodedWireChunk) {
// store the timestamp
pcmChunk->timestamp = decodedWireChunk->timestamp;
#if CONFIG_USE_PSRAM
pcmChunk->fragment->payload = (char *)heap_caps_malloc(decodedWireChunk->size, MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
if (pcmChunk->fragment->payload == NULL) {
ESP_LOGE(
TAG,
"Failed to allocate memory for pcm chunk fragment payload");
free_pcm_chunk(pcmChunk);
freeMem = heap_caps_get_free_size(MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM);
ret = -2;
}
else {
// copy the whole payload to our fragment
memcpy(pcmChunk->fragment->payload, decodedWireChunk->payload, decodedWireChunk->size);
pcmChunk->fragment->nextFragment = NULL;
pcmChunk->fragment->size = decodedWireChunk->size;
ret = 0;
}
#else
// we got valid memory for pcm_chunk_message_t
// first we try to allocated 32 bit aligned memory for payload
// check available memory first so we can decide if we need to fragment the data
@@ -667,6 +766,7 @@ int8_t insert_pcm_chunk(wire_chunk_message_t *decodedWireChunk) {
largestFreeBlock = heap_caps_get_largest_free_block(MALLOC_CAP_32BIT);
if (largestFreeBlock <= tmpSize) {
s = largestFreeBlock;
// TODO: DMA buffer needs to be changed also to one chunk size if sample rate changes
}
else {
s = tmpSize;
@@ -799,6 +899,7 @@ int8_t insert_pcm_chunk(wire_chunk_message_t *decodedWireChunk) {
ret = 0;
}
}
#endif
if (ret == 0) {
if (xQueueSendToBack(pcmChunkQueueHandle,
@@ -828,10 +929,11 @@ static void snapcast_sync_task(void *pvParameters) {
int64_t serverNow = 0;
int64_t age;
BaseType_t ret;
int64_t chunkDuration_us = WIRE_CHUNK_DURATION_MS * 1000;
int64_t chunkDuration_us;// = WIRE_CHUNK_DURATION_MS * 1000;
char *p_payload = NULL;
size_t size = 0;
uint32_t notifiedValue;
snapcastSetting_t snapcastSetting;
uint64_t timer_val;
const int32_t alarmValSub = 0;
int initialSync = 0;
@@ -840,13 +942,13 @@ static void snapcast_sync_task(void *pvParameters) {
int64_t buffer_us_local = 0;
pcm_chunk_fragment_t *fragment = NULL;
size_t written;
bool gotSnapserverConfig = false;
ESP_LOGI(TAG, "started sync task");
initialSync = 0;
snapcastSettingQueueHandle = xQueueCreate(1, sizeof(snapcastSetting_t));
currentDir = 1; // force adjust_apll to set correct playback speed
adjust_apll(0);
initialSync = 0;
shortMedianFilter.numNodes = SHORT_BUFFER_LEN;
shortMedianFilter.medianBuffer = shortMedianBuffer;
@@ -857,14 +959,40 @@ static void snapcast_sync_task(void *pvParameters) {
}
while (1) {
// get notification value which holds buffer_ms as communicated by
// snapserver
xTaskNotifyWait(pdFALSE, // Don't clear bits on entry.
pdFALSE, // Don't clear bits on exit
&notifiedValue, // Stores the notified value.
0);
// check if we got changed setting available, if so we need to reinitialize
ret = xQueueReceive(snapcastSettingQueueHandle, &snapcastSetting, 0);
if (ret == pdTRUE) {
buffer_us_local = (int64_t)(snapcastSetting.buffer_ms) * 1000LL;
buffer_us_local = (int64_t)notifiedValue * 1000LL;
chunkDuration_us = (int64_t)(snapcastSetting.chunkDuration_ms) * 1000LL;
chunkInBytes = (snapcastSetting.chunkDuration_ms * snapcastSetting.sampleRate * snapcastSetting.channels * (snapcastSetting.bits / 8)) / 1000;
if ((snapcastSetting.sampleRate > 0) && (snapcastSetting.bits) > 0 && (snapcastSetting.channels > 0)) {
i2s_custom_stop(I2S_NUM_0);
ret = player_setup_i2s(I2S_NUM_0, &currentSnapcastSetting);
if (ret < 0) {
ESP_LOGE(TAG, "player_setup_i2s failed: %d", ret);
return;
}
currentDir = 1; // force adjust_apll to set correct playback speed
adjust_apll(0);
i2s_custom_set_clk(I2S_NUM_0, snapcastSetting.sampleRate, snapcastSetting.bits, snapcastSetting.channels);
initialSync = 0;
}
ESP_LOGI(TAG, "snapserver config changed, buffer %dms, chunk %dms, sample rate %d, ch %d, bits %d", snapcastSetting.buffer_ms, snapcastSetting.chunkDuration_ms, snapcastSetting.sampleRate, snapcastSetting.channels, snapcastSetting.bits);
gotSnapserverConfig = true;
}
else if (gotSnapserverConfig == false) {
vTaskDelay(pdMS_TO_TICKS(10));
continue;
}
if (chnk == NULL) {
ret = xQueueReceive(pcmChunkQueueHandle, &chnk, pdMS_TO_TICKS(2000));
@@ -931,7 +1059,7 @@ static void snapcast_sync_task(void *pvParameters) {
// little earlier to account for context switch duration from
// freeRTOS, timer with 100ns ticks
i2s_custom_stop(I2S_PORT);
i2s_custom_stop(I2S_NUM_0);
if (MEDIANFILTER_Init(&shortMedianFilter)) {
ESP_LOGE(
@@ -947,7 +1075,7 @@ static void snapcast_sync_task(void *pvParameters) {
p_payload = fragment->payload;
size = fragment->size;
i2s_custom_init_dma_tx_queues(I2S_PORT, (uint8_t *)p_payload, size, &written);
i2s_custom_init_dma_tx_queues(I2S_NUM_0, (uint8_t *)p_payload, size, &written);
size -= written;
p_payload += written;
@@ -973,7 +1101,7 @@ static void snapcast_sync_task(void *pvParameters) {
// or use simple task delay for this
// vTaskDelay( pdMS_TO_TICKS(-age / 1000) );
i2s_custom_start(I2S_PORT);
i2s_custom_start(I2S_NUM_0);
// get timer value so we can get the real age
timer_get_counter_value(TIMER_GROUP_0, TIMER_1, &timer_val);
@@ -987,7 +1115,7 @@ static void snapcast_sync_task(void *pvParameters) {
if (size != 0) {
do {
written = 0;
if (i2s_custom_write(I2S_PORT, p_payload, (size_t)size, &written,
if (i2s_custom_write(I2S_NUM_0, p_payload, (size_t)size, &written,
portMAX_DELAY) != ESP_OK) {
ESP_LOGE(TAG, "i2s_playback_task: I2S write error");
}
@@ -1042,7 +1170,7 @@ static void snapcast_sync_task(void *pvParameters) {
// DMA buffer has a size of 1 chunk (e.g. 20ms) so next chunk
// we get from queue will be -20ms
const int64_t maxOffset = 50; //µs, softsync 1
const int64_t hardResyncThreshold = 1000; //µs, hard sync
const int64_t hardResyncThreshold = 3000; //µs, hard sync
avg = MEDIANFILTER_Insert(&shortMedianFilter, age + (-age_expect));
if (MEDIANFILTER_isFull(&shortMedianFilter) == 0) {
@@ -1085,7 +1213,7 @@ static void snapcast_sync_task(void *pvParameters) {
do {
written = 0;
if (i2s_custom_write(I2S_PORT, p_payload, (size_t)size, &written,
if (i2s_custom_write(I2S_NUM_0, p_payload, (size_t)size, &written,
portMAX_DELAY) != ESP_OK) {
ESP_LOGE(TAG, "i2s_playback_task: I2S write error");
}

View File

@@ -1,6 +1,6 @@
menu "Wifi Configuration"
config ENABLE_WIFI_PROVISIONING
bool "enable WiFi profisioning"
bool "enable WiFi provisioning"
default n
help
Enable WiFi provisioning so espressif APP can be used to provison WiFi credentials

View File

@@ -6,6 +6,7 @@
*/
#include <string.h>
#include <stdint.h>
#include "esp_event.h"
#include "esp_log.h"
@@ -61,6 +62,8 @@ xTaskHandle t_http_get_task;
xQueueHandle prot_queue;
static snapcastSetting_t snapcastSetting;
volatile int64_t clientDacLatency = 0;
uint32_t buffer_ms = 400;
uint8_t muteCH[4] = {0};
@@ -83,13 +86,9 @@ int timeval_subtract(struct timeval *result, struct timeval *x,
/* Logging tag */
static const char *TAG = "SNAPCAST";
static char buff[SNAPCAST_BUFF_LEN];
extern char mac_address[18];
extern EventGroupHandle_t s_wifi_event_group;
typedef enum codec_type_e { NONE, PCM, FLAC, OGG, OPUS } codec_type_t;
static QueueHandle_t playerChunkQueueHandle;
SemaphoreHandle_t timeSyncSemaphoreHandle = NULL;
@@ -118,20 +117,21 @@ static void http_get_task(void *pvParameters) {
char *start;
int sock = -1;
char base_message_serialized[BASE_MESSAGE_SIZE];
char time_message_serialized[TIME_MESSAGE_SIZE];
char *hello_message_serialized = NULL;
int result, size, id_counter;
struct timeval now, trx, tdif, ttx;
time_message_t time_message;
struct timeval tmpDiffToServer;
struct timeval lastTimeSync = {0, 0};
wire_chunk_message_t wire_chunk_message_last = {{0, 0}, 0, NULL};
tv_t wire_chunk_last_timestamp = {0, 0};
esp_timer_handle_t timeSyncMessageTimer = NULL;
const esp_timer_create_args_t tSyncArgs = {.callback = &time_sync_msg_cb,
.name = "tSyncMsg"};
int16_t frameSize = 960; // 960*2: 20ms, 960*1: 10ms
int16_t *audio = NULL;
int16_t pcm_size = 120;
uint16_t channels = CHANNELS;
uint16_t channels;
esp_err_t err = 0;
codec_header_message_t codec_header_message;
server_settings_message_t server_settings_message;
@@ -141,6 +141,7 @@ static void http_get_task(void *pvParameters) {
mdns_result_t *r;
OpusDecoder *opusDecoder = NULL;
codec_type_t codec = NONE;
bool chunkDurationDetected;
// create a timer to send time sync messages every x µs
esp_timer_create(&tSyncArgs, &timeSyncMessageTimer);
@@ -237,6 +238,7 @@ static void http_get_task(void *pvParameters) {
}
received_header = false;
chunkDurationDetected = false;
// init base message
base_message.type = SNAPCAST_MESSAGE_HELLO;
@@ -304,11 +306,21 @@ static void http_get_task(void *pvParameters) {
free(hello_message_serialized);
hello_message_serialized = NULL;
// init default setting
snapcastSetting.buffer_ms = 0;
snapcastSetting.codec = NONE;
snapcastSetting.bits = 0;
snapcastSetting.channels = 0;
snapcastSetting.sampleRate = 0;
snapcastSetting.chunkDuration_ms = 0;
snapcastSetting.volume = 0;
snapcastSetting.muted = false;
for (;;) {
size = 0;
result = 0;
while (size < BASE_MESSAGE_SIZE) {
result = recv(sock, &(buff[size]), BASE_MESSAGE_SIZE - size, 0);
result = recv(sock, &(base_message_serialized[size]), BASE_MESSAGE_SIZE - size, 0);
if (result < 0) {
break;
}
@@ -334,7 +346,7 @@ static void http_get_task(void *pvParameters) {
continue;
}
result = base_message_deserialize(&base_message, buff, size);
result = base_message_deserialize(&base_message, base_message_serialized, size);
if (result) {
ESP_LOGW(TAG, "Failed to read base message: %d", result);
continue;
@@ -348,26 +360,18 @@ static void http_get_task(void *pvParameters) {
// base_message.received.sec,
// base_message.received.usec );
start = buff;
// TODO: ensure this buffer is freed before task gets deleted
size = 0;
char *typedMsg = malloc(sizeof(char) * base_message.size);
if (typedMsg == NULL) {
ESP_LOGE(TAG, "Couldn't get memory for typed message");
// TODO: dynamically allocate memory for the next read!!!
// generate an error for now if we try to read more than
// SNAPCAST_BUFF_LEN in next lines
if (base_message.size > SNAPCAST_BUFF_LEN) {
ESP_LOGE(TAG, "base_message.size too big %d", base_message.size);
return;
return;
}
start = typedMsg;
while (size < base_message.size) {
if (size >= SNAPCAST_BUFF_LEN) {
ESP_LOGE(TAG, "Index too high");
return;
}
result = recv(sock, &(buff[size]), base_message.size - size, 0);
result = recv(sock, &(start[size]), base_message.size - size, 0);
if (result < 0) {
ESP_LOGW(TAG, "Failed to read from server: %d", result);
@@ -426,8 +430,28 @@ static void http_get_task(void *pvParameters) {
codec_header_message.codec);
codec = OPUS;
snapcastSetting.codec = codec;
snapcastSetting.bits = bits;
snapcastSetting.channels = channels;
snapcastSetting.sampleRate = rate;
} else if (strcmp(codec_header_message.codec, "pcm") == 0) {
codec = PCM;
memcpy(&channels, start + 22, sizeof(channels));
uint32_t rate;
memcpy(&rate, start + 24, sizeof(rate));
uint16_t bits;
memcpy(&bits, start + 34, sizeof(bits));
ESP_LOGI(TAG, "%s sampleformat: %d:%d:%d",
codec_header_message.codec, rate, bits, channels);
snapcastSetting.codec = codec;
snapcastSetting.bits = bits;
snapcastSetting.channels = channels;
snapcastSetting.sampleRate = rate;
} else {
codec = NONE;
@@ -455,6 +479,10 @@ static void http_get_task(void *pvParameters) {
case SNAPCAST_MESSAGE_WIRE_CHUNK: {
if (!received_header) {
if (typedMsg != NULL) {
free(typedMsg);
}
continue;
}
@@ -474,32 +502,6 @@ static void http_get_task(void *pvParameters) {
// wire_chunk_message.timestamp.sec,
// wire_chunk_message.timestamp.usec);
// TODO: detect chunk duration dynamically and allocate buffers
// accordingly.
struct timeval tv_d1, tv_d2, tv_d3;
tv_d1.tv_sec = wire_chunk_message.timestamp.sec;
tv_d1.tv_usec = wire_chunk_message.timestamp.usec;
tv_d2.tv_sec = wire_chunk_message_last.timestamp.sec;
tv_d2.tv_usec = wire_chunk_message_last.timestamp.usec;
timersub(&tv_d1, &tv_d2, &tv_d3);
wire_chunk_message_last.timestamp = wire_chunk_message.timestamp;
// ESP_LOGI(TAG, "chunk duration %ld.%06ld", tv_d3.tv_sec,
// tv_d3.tv_usec);
if ((tv_d3.tv_sec * 1000000 + tv_d3.tv_usec) >
(WIRE_CHUNK_DURATION_MS * 1000)) {
ESP_LOGE(TAG,
"wire chnk with size: %d, timestamp %d.%d, duration "
"%ld.%06ld",
wire_chunk_message.size,
wire_chunk_message.timestamp.sec,
wire_chunk_message.timestamp.usec, tv_d3.tv_sec,
tv_d3.tv_usec);
wire_chunk_message_free(&wire_chunk_message);
continue;
}
// store chunk's timestamp, decoder callback
// will need it later
tv_t timestamp;
@@ -512,11 +514,11 @@ static void http_get_task(void *pvParameters) {
if (audio == NULL) {
#if CONFIG_USE_PSRAM
audio = (int16_t *)heap_caps_malloc(
frameSize * CHANNELS * (BITS_PER_SAMPLE / 8),
frameSize * snapcastSetting.channels * (snapcastSetting.bits / 8),
MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); // 960*2: 20ms, 960*1: 10ms
#else
audio = (int16_t *)malloc(
frameSize * CHANNELS * (BITS_PER_SAMPLE / 8)); // 960*2: 20ms, 960*1: 10ms
frameSize * snapcastSetting.channels * (snapcastSetting.bits / 8)); // 960*2: 20ms, 960*1: 10ms
#endif
}
@@ -536,12 +538,12 @@ static void http_get_task(void *pvParameters) {
// 960*2: 20ms, 960*1: 10ms
#if CONFIG_USE_PSRAM
audio = (int16_t *)heap_caps_realloc(
audio, pcm_size * CHANNELS * (BITS_PER_SAMPLE / 8), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); // 2 channels + 2 Byte per sample == int32_t
audio, pcm_size * snapcastSetting.channels * (snapcastSetting.bits / 8), MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); // 2 channels + 2 Byte per sample == int32_t
#else
audio = (int16_t *)realloc(
audio, pcm_size * CHANNELS * (BITS_PER_SAMPLE / 8));
audio, pcm_size * snapcastSetting.channels * (snapcastSetting.bits / 8));
// audio = (int16_t *)heap_caps_realloc(
// (int32_t *)audio, frameSize * CHANNELS * (BITS_PER_SAMPLE / 8), MALLOC_CAP_32BIT); // 960*2: 20ms, 960*1: 10ms
// (int32_t *)audio, frameSize * CHANNELS * (BITS_PER_SAMPLE / 8), MALLOC_CAP_32BIT);
#endif
@@ -562,11 +564,25 @@ static void http_get_task(void *pvParameters) {
} else {
wire_chunk_message_t pcm_chunk_message;
pcm_chunk_message.size = frame_size * CHANNELS * (BITS_PER_SAMPLE / 8);
pcm_chunk_message.size = frame_size * snapcastSetting.channels * (snapcastSetting.bits / 8);
pcm_chunk_message.payload = audio;
pcm_chunk_message.timestamp = timestamp;
snapcastSetting.chunkDuration_ms = (1000UL * pcm_chunk_message.size) / (uint32_t)(snapcastSetting.channels * (snapcastSetting.bits / 8)) / snapcastSetting.sampleRate;
if (player_send_snapcast_setting(snapcastSetting) < 0) {
ESP_LOGE(TAG, "Failed to notify sync task about codec. Did you init player?");
return;
}
// if (snapcastSetting.chunkDuration_ms > 30) {
// ESP_LOGE(TAG, "We can't get that big chunks on this platform. RAM is a scarce good!");
//
// return;
// }
#if CONFIG_USE_DSP_PROCESSOR
dsp_setup_flow(500, snapcastSetting.sampleRate, snapcastSetting.chunkDuration_ms);
dsp_processor(pcm_chunk_message.payload,
pcm_chunk_message.size, dspFlow);
#endif
@@ -580,16 +596,14 @@ static void http_get_task(void *pvParameters) {
case PCM: {
wire_chunk_message_t pcm_chunk_message;
uint16_t len = (CONFIG_PCM_SAMPLE_RATE * CONFIG_WIRE_CHUNK_DURATION_MS / 1000);
if (audio == NULL) {
#if CONFIG_USE_PSRAM
audio = (int16_t *)heap_caps_malloc(
len * CHANNELS * (BITS_PER_SAMPLE / 8),
pcm_chunk_message.size * sizeof(char),
MALLOC_CAP_8BIT | MALLOC_CAP_SPIRAM); // 960*2: 20ms, 960*1: 10ms
#else
audio = (int16_t *)malloc(
len * CHANNELS * (BITS_PER_SAMPLE / 8)); // 960*2: 20ms, 960*1: 10ms
audio = (int16_t *)malloc(pcm_chunk_message.size * sizeof(char));
#endif
}
@@ -608,7 +622,15 @@ static void http_get_task(void *pvParameters) {
memcpy(pcm_chunk_message.payload, start,
pcm_chunk_message.size);
snapcastSetting.chunkDuration_ms = (1000UL * pcm_chunk_message.size) / (uint32_t)(snapcastSetting.channels * (snapcastSetting.bits / 8)) / snapcastSetting.sampleRate;
if (player_send_snapcast_setting(snapcastSetting) < 0) {
ESP_LOGE(TAG, "Failed to notify sync task about codec. Did you init player?");
return;
}
#if CONFIG_USE_DSP_PROCESSOR
dsp_setup_flow(500, snapcastSetting.sampleRate, snapcastSetting.chunkDuration_ms);
dsp_processor(pcm_chunk_message.payload,
pcm_chunk_message.size, dspFlow);
#endif
@@ -622,6 +644,8 @@ static void http_get_task(void *pvParameters) {
default: {
ESP_LOGE(TAG, "Decoder not supported");
return;
break;
}
}
@@ -658,13 +682,18 @@ static void http_get_task(void *pvParameters) {
muteCH[2] = server_settings_message.muted;
muteCH[3] = server_settings_message.muted;
snapcastSetting.buffer_ms = server_settings_message.buffer_ms;
snapcastSetting.muted = server_settings_message.muted;
snapcastSetting.volume = server_settings_message.volume;
// Volume setting using ADF HAL abstraction
audio_hal_set_mute(board_handle->audio_hal,
server_settings_message.muted);
audio_hal_set_volume(board_handle->audio_hal,
server_settings_message.volume);
if (player_notify_buffer_ms(buffer_ms) < 0) {
//if (player_notify_buffer_ms(buffer_ms) < 0) {
if (player_send_snapcast_setting(snapcastSetting) < 0) {
ESP_LOGE(TAG, "Failed to notify sync task. Did you init player?");
return;
@@ -780,6 +809,10 @@ static void http_get_task(void *pvParameters) {
break;
}
if (typedMsg != NULL) {
free(typedMsg);
}
}
if (received_header == true) {
@@ -810,7 +843,7 @@ static void http_get_task(void *pvParameters) {
memset(&time_message, 0, sizeof(time_message));
result =
time_message_serialize(&time_message, buff, SNAPCAST_BUFF_LEN);
time_message_serialize(&time_message, time_message_serialized, TIME_MESSAGE_SIZE);
if (result) {
ESP_LOGI(TAG, "Failed to serialize time message\r\b");
continue;
@@ -827,7 +860,7 @@ static void http_get_task(void *pvParameters) {
break; // stop for(;;) will try to reconnect then
}
result = send(sock, buff, TIME_MESSAGE_SIZE, 0);
result = send(sock, time_message_serialized, TIME_MESSAGE_SIZE, 0);
if (result < 0) {
ESP_LOGW(TAG, "error writing timesync msg to socket: %s",
strerror(errno));
@@ -856,9 +889,11 @@ void app_main(void) {
ESP_ERROR_CHECK(ret);
esp_log_level_set("*", ESP_LOG_INFO);
// esp_log_level_set("c_I2S", ESP_LOG_NONE); //
esp_log_level_set("HEADPHONE", ESP_LOG_NONE); // if enabled these cause a timer srv stack overflow
esp_log_level_set("gpio", ESP_LOG_NONE); //
esp_timer_init();
ESP_LOGI(TAG, "Start codec chip");
@@ -870,9 +905,9 @@ void app_main(void) {
i2s_mclk_gpio_select(0, 0);
// setup_ma120();
#if CONFIG_USE_DSP_PROCESSOR
dsp_setup_flow(500, SAMPLE_RATE);
#endif
#if CONFIG_USE_DSP_PROCESSOR
dsp_setup_flow(500, 44100, 20); // init with default value
#endif
ESP_LOGI(TAG, "init player");
playerChunkQueueHandle = init_player();

View File

@@ -283,15 +283,11 @@ CONFIG_ESP_DISPATCHER_DELEGATE_STACK_SIZE=4096
# end of ADF Features
#
# ESP32 audio buffer and I2S pin config
# ESP32 audio buffer and I2S config
#
CONFIG_USE_DSP_PROCESSOR=y
CONFIG_BITS_PER_SAMPLE=16
CONFIG_CHANNELS=2
CONFIG_PCM_SAMPLE_RATE=48000
CONFIG_WIRE_CHUNK_DURATION_MS=20
CONFIG_USE_BIQUAD_ASM=y
# end of ESP32 audio buffer and I2S pin config
# end of ESP32 audio buffer and I2S config
#
# SNTP Configuration

View File

@@ -283,15 +283,12 @@ CONFIG_ESP_DISPATCHER_DELEGATE_STACK_SIZE=4096
# end of ADF Features
#
# ESP32 audio buffer and I2S pin config
# ESP32 audio buffer and I2S config
#
CONFIG_USE_PSRAM=y
CONFIG_USE_DSP_PROCESSOR=y
CONFIG_BITS_PER_SAMPLE=16
CONFIG_CHANNELS=2
CONFIG_PCM_SAMPLE_RATE=48000
CONFIG_WIRE_CHUNK_DURATION_MS=20
CONFIG_USE_BIQUAD_ASM=y
# end of ESP32 audio buffer and I2S pin config
# end of ESP32 audio buffer and I2S config
#
# SNTP Configuration
@@ -476,6 +473,7 @@ CONFIG_ESP_TLS_USING_MBEDTLS=y
#
# ESP32-specific
#
CONFIG_ESP32_ECO3_CACHE_LOCK_FIX=y
CONFIG_ESP32_REV_MIN_0=y
# CONFIG_ESP32_REV_MIN_1 is not set
# CONFIG_ESP32_REV_MIN_2 is not set
@@ -486,7 +484,68 @@ CONFIG_ESP32_DPORT_WORKAROUND=y
# CONFIG_ESP32_DEFAULT_CPU_FREQ_160 is not set
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240
# CONFIG_ESP32_SPIRAM_SUPPORT is not set
CONFIG_ESP32_SPIRAM_SUPPORT=y
#
# SPI RAM config
#
CONFIG_SPIRAM_TYPE_AUTO=y
# CONFIG_SPIRAM_TYPE_ESPPSRAM16 is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM32 is not set
# CONFIG_SPIRAM_TYPE_ESPPSRAM64 is not set
CONFIG_SPIRAM_SIZE=-1
# CONFIG_SPIRAM_SPEED_40M is not set
CONFIG_SPIRAM_SPEED_80M=y
CONFIG_SPIRAM=y
CONFIG_SPIRAM_BOOT_INIT=y
# CONFIG_SPIRAM_IGNORE_NOTFOUND is not set
# CONFIG_SPIRAM_USE_MEMMAP is not set
CONFIG_SPIRAM_USE_CAPS_ALLOC=y
# CONFIG_SPIRAM_USE_MALLOC is not set
CONFIG_SPIRAM_MEMTEST=y
# CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP is not set
# CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY is not set
CONFIG_SPIRAM_CACHE_WORKAROUND=y
#
# SPIRAM cache workaround debugging
#
CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_MEMW=y
# CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_DUPLDST is not set
# CONFIG_SPIRAM_CACHE_WORKAROUND_STRATEGY_NOPS is not set
# end of SPIRAM cache workaround debugging
CONFIG_SPIRAM_BANKSWITCH_ENABLE=y
CONFIG_SPIRAM_BANKSWITCH_RESERVE=8
# CONFIG_SPIRAM_OCCUPY_HSPI_HOST is not set
CONFIG_SPIRAM_OCCUPY_VSPI_HOST=y
# CONFIG_SPIRAM_OCCUPY_NO_HOST is not set
#
# PSRAM clock and cs IO for ESP32-DOWD
#
CONFIG_D0WD_PSRAM_CLK_IO=17
CONFIG_D0WD_PSRAM_CS_IO=16
# end of PSRAM clock and cs IO for ESP32-DOWD
#
# PSRAM clock and cs IO for ESP32-D2WD
#
CONFIG_D2WD_PSRAM_CLK_IO=9
CONFIG_D2WD_PSRAM_CS_IO=10
# end of PSRAM clock and cs IO for ESP32-D2WD
#
# PSRAM clock and cs IO for ESP32-PICO
#
CONFIG_PICO_PSRAM_CS_IO=10
# end of PSRAM clock and cs IO for ESP32-PICO
# CONFIG_SPIRAM_CUSTOM_SPIWP_SD3_PIN is not set
CONFIG_SPIRAM_SPIWP_SD3_PIN=7
# CONFIG_SPIRAM_2T_MODE is not set
# end of SPI RAM config
# CONFIG_ESP32_TRAX is not set
CONFIG_ESP32_TRACEMEM_RESERVE_DRAM=0x0
# CONFIG_ESP32_UNIVERSAL_MAC_ADDRESSES_TWO is not set
@@ -651,7 +710,6 @@ CONFIG_ESP_NETIF_TCPIP_ADAPTER_COMPATIBLE_LAYER=y
CONFIG_ESP_SYSTEM_PANIC_PRINT_REBOOT=y
# CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT is not set
# CONFIG_ESP_SYSTEM_PANIC_GDBSTUB is not set
CONFIG_ESP_SYSTEM_PD_FLASH=y
#
# Memory protection
@@ -673,20 +731,22 @@ CONFIG_ESP_TIMER_IMPL_TG0_LAC=y
#
# Wi-Fi
#
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=2
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=12
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=8
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32
# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set
CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1
CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=6
CONFIG_ESP32_WIFI_CACHE_TX_BUFFER_NUM=32
CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32
# CONFIG_ESP32_WIFI_CSI_ENABLED is not set
CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y
CONFIG_ESP32_WIFI_TX_BA_WIN=2
CONFIG_ESP32_WIFI_TX_BA_WIN=4
CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y
CONFIG_ESP32_WIFI_RX_BA_WIN=2
CONFIG_ESP32_WIFI_RX_BA_WIN=4
# CONFIG_ESP32_WIFI_AMSDU_TX_ENABLED is not set
CONFIG_ESP32_WIFI_NVS_ENABLED=y
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0=y
# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1 is not set
# CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_0 is not set
CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1=y
CONFIG_ESP32_WIFI_SOFTAP_BEACON_MAX_LEN=752
CONFIG_ESP32_WIFI_MGMT_SBUF_NUM=32
# CONFIG_ESP32_WIFI_DEBUG_LOG_ENABLE is not set
@@ -746,6 +806,7 @@ CONFIG_FATFS_LFN_NONE=y
CONFIG_FATFS_FS_LOCK=0
CONFIG_FATFS_TIMEOUT_MS=10000
CONFIG_FATFS_PER_FILE_CACHE=y
CONFIG_FATFS_ALLOC_PREFER_EXTRAM=y
# CONFIG_FATFS_USE_FASTSEEK is not set
# end of FAT Filesystem support
@@ -785,7 +846,7 @@ CONFIG_FMB_TIMER_INDEX=0
CONFIG_FREERTOS_NO_AFFINITY=0x7FFFFFFF
CONFIG_FREERTOS_CORETIMER_0=y
# CONFIG_FREERTOS_CORETIMER_1 is not set
CONFIG_FREERTOS_HZ=100
CONFIG_FREERTOS_HZ=1000
CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y
# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE is not set
# CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL is not set
@@ -862,7 +923,7 @@ CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=y
# CONFIG_LWIP_L2_TO_L3_COPY is not set
# CONFIG_LWIP_IRAM_OPTIMIZATION is not set
CONFIG_LWIP_TIMERS_ONDEMAND=y
CONFIG_LWIP_MAX_SOCKETS=3
CONFIG_LWIP_MAX_SOCKETS=6
# CONFIG_LWIP_USE_ONLY_LWIP_SELECT is not set
# CONFIG_LWIP_SO_LINGER is not set
CONFIG_LWIP_SO_REUSE=y
@@ -986,6 +1047,7 @@ CONFIG_LWIP_HOOK_NETCONN_EXT_RESOLVE_NONE=y
# mbedTLS
#
CONFIG_MBEDTLS_INTERNAL_MEM_ALLOC=y
# CONFIG_MBEDTLS_EXTERNAL_MEM_ALLOC is not set
# CONFIG_MBEDTLS_DEFAULT_MEM_ALLOC is not set
# CONFIG_MBEDTLS_CUSTOM_MEM_ALLOC is not set
CONFIG_MBEDTLS_ASYMMETRIC_CONTENT_LEN=y
@@ -1367,7 +1429,8 @@ CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_ACL_CONN_EFF=0
CONFIG_BTDM_CONTROLLER_BR_EDR_MAX_SYNC_CONN_EFF=0
CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0
CONFIG_ADC2_DISABLE_DAC=y
# CONFIG_SPIRAM_SUPPORT is not set
CONFIG_SPIRAM_SUPPORT=y
# CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is not set
CONFIG_TRACEMEM_RESERVE_DRAM=0x0
# CONFIG_TWO_UNIVERSAL_MAC_ADDRESS is not set
CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y

1474
sdkconfig_NO_SPI_RAM Normal file

File diff suppressed because it is too large Load Diff

1544
sdkconfig_SPI_RAM Normal file

File diff suppressed because it is too large Load Diff