Go Down

Topic: Setting up I2S on ESP32 ands WM8978 (Read 1 time) previous topic - next topic

beatbot

I'm trying to get I2S audio working with an ESP32 and WM8978 codec, using the TTGO TAudio dev board. Currently, I'm trying to implement the I2S example code provided by Espressif using the Arduino ESP32 framework.

I'm using a library for sending I2C commands to the codec, and that works fine - I'm able to setup the analog patch in the codec and change gain levels, but getting the DAC/ADC to work has been more of a challenge.

Currently, the ESP32 I2S function i2s_driver_install returns an error "I2S: clkmdiv is too large".  Looking at the driver on github it seems like this is because either the bits_per_sample or samplerate are too small, but they are currently set at the max.
https://github.com/espressif/esp-idf/blob/master/components/driver/i2s.c

Also, I note that i2s_write() returns a 'not declared in this scope' error, which makes me think that the esp32 arduino framework is out of date? But there are examples using i2s_write_bytes() which seem to be working for people.

I don't see what I am doing wrong, based on my reference examples below. Any suggestions of things to try?

Code: [Select]
/*********
Test program for implementing wavetable synthesis using the
WM8978 Audio Codec

Based on the espressif sample i2s code:
https://github.com/espressif/esp-idf/tree/97eecfa1b2b95a6f77e8e9ffcb676ded687ab68f/examples/peripherals/i2s

And the TTGO TAudio demo sketch:
https://github.com/LilyGO/TTGO-TAudio

And the DFRobot NuvotonDuino:
https://github.com/DFRobot/NuvotonDuino

----------------

*********/
//WM8978 I2S dependencies
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2s.h"
#include "esp_system.h"

//WM8978 I2C dependencies
#include <types.h>
#include <WM8978.h> //borrowed from the NuvotonDuino example
#include <Wire.h>

const byte I2S_SERIAL_DEBUG = 1;
const byte SAMPLE_RATE  = 48000;   
const byte I2S_NUM = 0;

//16-bit 128-sample sine wavetable
int sineT[128]= {0, 1620, 3237, 4845, 6442, 8023, 9584, 11122,
12633, 14113, 15558, 16965, 18331, 19651, 20924, 22146,
23313, 24423, 25474, 26462, 27385, 28241, 29029, 29745,
30388, 30957, 31451, 31867, 32205, 32465, 32645, 32745,
32765, 32705, 32565, 32345, 32046, 31668, 31213, 30682,
30076, 29396, 28644, 27822, 26931, 25975, 24956, 23875,
22736, 21541, 20294, 18997, 17653, 16266, 14840, 13377,
11881, 10356, 8806, 7234, 5645, 4042, 2429, 810, -810,
-2429, -4042, -5646, -7235, -8807, -10357, -11881, -13377,
-14840, -16267, -17653, -18997, -20294, -21542, -22736,
-23875, -24956, -25976, -26932, -27822, -28644, -29396,
-30076, -30682, -31214, -31668, -32046, -32345, -32565, -32705,
-32765, -32745, -32645, -32465, -32205, -31867, -31450, -30957,
-30388, -29745, -29028, -28241, -27385, -26461, -25473, -24423,
-23313, -22145, -20924, -19651, -18330, -16965, -15557, -14112,
-12632, -11122, -9584, -8022, -6441, -4845, -3236, -1620};

//i2s configuration
int i2s_num = 0; // i2s port number
i2s_config_t i2s_config = {
     .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_RX),
     .sample_rate = SAMPLE_RATE,
     .bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
     .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT,
     .communication_format = (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 = 3,
     .dma_buf_len = 1024,
     .use_apll = false
};
   
//updated I2S pins for tAudio
i2s_pin_config_t pin_config = {
    .bck_io_num = 33, //this is BCK pin
    .ws_io_num = 25, // this is LRCK pin
    .data_out_num = 26, // this is DATA output pin
    .data_in_num = 27   //
};

uint32_t missedByteCounter = 0; //debug variable

/****************************************
 * I2S FUNCTIONS
  *****************************************/

//this function just streams samples from the wavetable to the codec
static uint16_t setup_triangle_sine_waves(int bits)
{
  static byte index = 0;
   uint16_t samples_data = sineT[index/2] + 32765;
   //write to codec below
   int bytes_written = i2s_write_bytes((i2s_port_t)I2S_NUM, (const char *)&samples_data, 2, 100);
   
  //i2s_write((i2s_port_t)I2S_NUM, (const char *)&samples_data, 2, &bytes_written, 100);
   
  if (bytes_written > 0)  index++;
  else missedByteCounter++;
  index+=11;
 // missedByteCounter+=bytes_written;
   return samples_data;
}

void i2sSetup()
{
    i2s_driver_install((i2s_port_t)I2S_NUM, &i2s_config, 0, NULL);
    i2s_set_pin((i2s_port_t)I2S_NUM, &pin_config);
}

void i2sLoop(){
  static uint32_t timer = 0;
  int interval = 1000;
  uint16_t val = setup_triangle_sine_waves(0);
 
  if (I2S_SERIAL_DEBUG) {
    if( millis() - timer > interval){
      timer = millis();
      Serial.print(" i2s buffer full cycles: ");
      Serial.println( missedByteCounter );
      Serial.println(val);
      missedByteCounter = 0;
    }
  }
}

/****************************************
 * WM8978 I2C SETUP
 * Uses the WM8978 I2C library distributed with the NuovoDuino
  *****************************************/
  void wm8978Setup() {
  Wire.begin(19,18); //(SDA,SCL,Frequency)
  WM8978_Init();
 
  unsigned char dacen = 1;
  unsigned char adcen = 1;
  unsigned char micen = 1;
  unsigned char lineinen = 0;
  unsigned char auxen = 0;
  unsigned char bpsen = 1;

  unsigned char initVal = WM8978_Init();

  WM8978_ADDA_Cfg(dacen, adcen);
  WM8978_Input_Cfg(micen, lineinen, auxen);
  WM8978_Output_Cfg(dacen, bpsen);
  WM8978_MIC_Gain(50);
  WM8978_SPKvol_Set(30);
  WM8978_HPvol_Set(50,50);
  //WM8978_ALC_Set(1,7,3);
  WM8978_Write_Reg(3,0xFF);
  WM8978_I2S_Cfg(2,0); //format, bit-length
  WM8978_Write_Reg(7,4<<1);//sets sample rate to 12kHz
  WM8978_Write_Reg(11,0xFF);
  WM8978_Write_Reg(12,0xFF|1<<8);
} //wm8978Setup

/****************************************
 * SETUP AND LOOP
 *
  *****************************************/
 
void setup() {
  Serial.begin(115200);
  //wm8978Setup();
  i2sSetup();
}

void loop(){
  i2sLoop();
}

MarkT

I'm trying to get I2S audio working with an ESP32 and WM8978 codec, using the TTGO TAudio dev board. Currently, I'm trying to implement the I2S example code provided by Espressif using the Arduino ESP32 framework.

I'm using a library for sending I2C commands to the codec, and that works fine - I'm able to setup the analog patch in the codec and change gain levels, but getting the DAC/ADC to work has been more of a challenge.

Currently, the ESP32 I2S function i2s_driver_install returns an error "I2S: clkmdiv is too large".  Looking at the driver on github it seems like this is because either the bits_per_sample or samplerate are too small, but they are currently set at the max.
https://github.com/espressif/esp-idf/blob/master/components/driver/i2s.c
Code: [Select]

const byte SAMPLE_RATE  = 48000;   

See the issue with the sample rate now?
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up