I2s using fixed_mclk
Posted: Wed Sep 12, 2018 8:24 pm
What is the correct syntax for using fixed_mclk in I2S communication?
I have the following code:
The hardware is CJMCU-1334 for TX, which is based around a UDA1334 chip. This chip has a PLL built in for the correct mclk.
CJMCU-1802 for RX, which is based upon PCM1802 chip. This chip has no such PLL built in and requires an external mclk signal.
I do get sound throughput, after days and days of searching, however it is extremely noisy.
I believe the mclk supplied by this code is not right and I want to tune it.
when compiling using '.fixed_mclk' the following message appears:
'i2s_config_t' has no non-static data member named 'fixed_mclk'
The following questions arise: what is the correct syntax? what are the boundaries/units?
I have the following code:
Code: Select all
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "nvs_flash.h"
#include "driver/i2s.h"
#include <math.h>
#include "soc/rtc_io_reg.h"
#include "soc/sens_reg.h"
#define SAMPLE_RATE (44100)
#define I2S_NUM_0 (0)
#define I2S_NUM_1 (1)
#define WAVE_FREQ_HZ (440)
#define SAMPLE_PER_CYCLE (SAMPLE_RATE/WAVE_FREQ_HZ)
long RX_sample_val[2];
int returned;
unsigned int i;
long TX_sample_val[2];
long Temp_audio[2];
int TX_install_ok, TX_set_pin_ok;
int RX_install_ok, RX_set_pin_ok;
float sin_float, triangle_float, triangle_step = 65536.0 / SAMPLE_PER_CYCLE;
i2s_config_t i2s_config_TX = {
.mode = static_cast<i2s_mode_t>(I2S_MODE_MASTER | I2S_MODE_TX), // TX only
.sample_rate = 44100,//SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_24BIT,//I2S_BITS_PER_SAMPLE_16BIT, //16-bit per channel
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
.communication_format = static_cast<i2s_comm_format_t>(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // high interrupt priority
.dma_buf_count = 2,
.dma_buf_len = 128,
// .use_apll = true//
};
i2s_pin_config_t pin_config_TX = {
.bck_io_num = 14,
.ws_io_num = 12,
.data_out_num = 22,
.data_in_num = -1
};
i2s_config_t i2s_config_RX = {
.mode = static_cast<i2s_mode_t>(I2S_MODE_MASTER | I2S_MODE_RX), // RX only
.sample_rate = 44100,//SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_24BIT,//I2S_BITS_PER_SAMPLE_16BIT, //16-bit per channel
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
.communication_format = static_cast<i2s_comm_format_t>(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, // high interrupt priority
.dma_buf_count =2,
.dma_buf_len = 128, //
.use_apll = true,
// .fixed_mclk = 169344
};
i2s_pin_config_t pin_config_RX = {
.bck_io_num =26,
.ws_io_num = 25,
.data_out_num = -1,
.data_in_num = 23
};
void setup()
{
Serial.begin(115200);
nvs_flash_init();
pinMode(13, OUTPUT);//FSYNC
//start I2S transmitter
TX_install_ok = i2s_driver_install(static_cast<i2s_port_t>I2S_NUM_1, &i2s_config_TX, 0, NULL);
TX_set_pin_ok = i2s_set_pin(static_cast<i2s_port_t>I2S_NUM_1, &pin_config_TX);
//start I2S receiver
RX_install_ok = i2s_driver_install(static_cast<i2s_port_t>I2S_NUM_0, &i2s_config_RX, 0, NULL);
RX_set_pin_ok = i2s_set_pin(static_cast<i2s_port_t>I2S_NUM_0, &pin_config_RX);
//Set mclk output to pin 0 for I2S RX
REG_WRITE(PIN_CTRL, 0b111111110000);
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
Serial.print(" esp ok: ");
Serial.print(ESP_OK);
Serial.print("TX install ok: ");
Serial.print(TX_install_ok);
Serial.print(" TX set pin ok: ");
Serial.print(TX_set_pin_ok);
Serial.print("RX install ok: ");
Serial.print(RX_install_ok);
Serial.print(" RX set pin ok: ");
Serial.print(RX_set_pin_ok);
TaskHandle_t Task1, Task2;
xTaskCreatePinnedToCore(
codeForTask1,
"commTask",
1500,
NULL,
1,
&Task1,
0);
delay(500); // needed to start-up task1
xTaskCreatePinnedToCore(
codeForTask2,
"driveTask",
1000,
NULL,
1,
&Task2,
1);
}
void codeForTask1( void * parameter )
{
for (;;)
{
digitalWrite(13, HIGH);
returned = i2s_pop_sample(static_cast<i2s_port_t>I2S_NUM_0, (char *)&RX_sample_val[0], portMAX_DELAY);
digitalWrite(13, LOW);
TX_sample_val[0] = RX_sample_val[0] & 0x00000000; //ignore right channel for now
//shift and also reduce some noise and add zero offset
Temp_audio[1] = (RX_sample_val[1] / 1024) + 125288;
//copy input sound to output
TX_sample_val[1] = RX_sample_val[1];
// Test noise example for output test
//
// triangle_float = -32767;
//
// for(i = 0; i < SAMPLE_PER_CYCLE; i++) {
// sin_float = sin(i * PI / 180.0);
// if(sin_float >= 0)
// triangle_float += triangle_step;
// else
// triangle_float -= triangle_step;
// sin_float *= 32767;
//
// TX_sample_val[0] = 0L;
// TX_sample_val[0] += (short)triangle_float;
// TX_sample_val[0] = TX_sample_val[0] << 16;
// TX_sample_val[0] += (short) sin_float;
i2s_push_sample(static_cast<i2s_port_t>I2S_NUM_1, (char *)&TX_sample_val[0], portMAX_DELAY);
// }
}
}
void codeForTask2( void * parameter )
{
for (;;)
{
//// Debug to serial monitor
// Serial.print("right: ");
// Serial.print(TX_sample_val[0]);
// Serial.print(" left: ");
// Serial.println(TX_sample_val[1]);
}
}
//
void loop()
{
delay(1000);
}
CJMCU-1802 for RX, which is based upon PCM1802 chip. This chip has no such PLL built in and requires an external mclk signal.
I do get sound throughput, after days and days of searching, however it is extremely noisy.
I believe the mclk supplied by this code is not right and I want to tune it.
when compiling using '.fixed_mclk' the following message appears:
'i2s_config_t' has no non-static data member named 'fixed_mclk'
The following questions arise: what is the correct syntax? what are the boundaries/units?