mirror of
https://github.com/espressif/ESP8266_RTOS_SDK.git
synced 2025-05-30 06:59:02 +08:00
feature(i2s): add i2s driver
This commit is contained in:
9
examples/peripherals/i2s/Makefile
Normal file
9
examples/peripherals/i2s/Makefile
Normal file
@ -0,0 +1,9 @@
|
||||
#
|
||||
# This is a project Makefile. It is assumed the directory this Makefile resides in is a
|
||||
# project subdirectory.
|
||||
#
|
||||
|
||||
PROJECT_NAME := i2s
|
||||
|
||||
include $(IDF_PATH)/make/project.mk
|
||||
|
68
examples/peripherals/i2s/README.md
Normal file
68
examples/peripherals/i2s/README.md
Normal file
@ -0,0 +1,68 @@
|
||||
# I2S Example
|
||||
|
||||
(See the README.md file in the upper level 'examples' directory for more information about examples.)
|
||||
|
||||
In this example, we generate a 100Hz triangle and sine wave and send it out from left and right channels at a sample rate of 36kHz through the I2S bus.
|
||||
|
||||
## How to Use Example
|
||||
|
||||
### Hardware Required
|
||||
|
||||
* A development board with ESP8266 SoC (e.g., ESP8266-DevKitC, etc.)
|
||||
* A USB cable for power supply and programming
|
||||
|
||||
### Configure the Project
|
||||
|
||||
```
|
||||
make menuconfig
|
||||
```
|
||||
|
||||
* Set serial port under Serial Flasher Options.
|
||||
|
||||
### Build and Flash
|
||||
|
||||
Build the project and flash it to the board, then run monitor tool to view serial output:
|
||||
|
||||
```
|
||||
make -j4 flash monitor
|
||||
```
|
||||
|
||||
(To exit the serial monitor, type ``Ctrl-]``.)
|
||||
|
||||
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
|
||||
|
||||
## Example Output
|
||||
|
||||
Running this example, you will see the Bits per Sample changes every 5 seconds after you have run this example. You can use `i2s_set_clk` to change the Bits per Sample and the Sample Rate. The output log can be seen below:
|
||||
|
||||
```
|
||||
Test bits=24 free mem=78188, written data=2880
|
||||
I (5655) i2s: DMA Malloc info, datalen=blocksize=480, dma_buf_count=6
|
||||
|
||||
Test bits=16 free mem=78188, written data=1440
|
||||
I (10735) i2s: DMA Malloc info, datalen=blocksize=240, dma_buf_count=6
|
||||
|
||||
Test bits=24 free mem=78188, written data=2880
|
||||
I (15835) i2s: DMA Malloc info, datalen=blocksize=480, dma_buf_count=6
|
||||
|
||||
Test bits=16 free mem=78188, written data=1440
|
||||
I (20915) i2s: DMA Malloc info, datalen=blocksize=240, dma_buf_count=6
|
||||
```
|
||||
|
||||
If you have a logic analyzer, you can use a logic analyzer to grab online data. The following table describes the pins we use by default (Note that you can also use other pins for the same purpose).
|
||||
|
||||
| pin name| function | gpio_num |
|
||||
|:---:|:---:|:---:|
|
||||
| MCLK|main clock | GPIO_NUM_4 |
|
||||
| WS |word select| GPIO_NUM_2 |
|
||||
| SCK |continuous serial clock| GPIO_NUM_15 |
|
||||
| SD |serial data| GPIO_NUM_3 |
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
* Program upload failure
|
||||
|
||||
* Hardware connection is not correct: run `make monitor`, and reboot your board to see if there are any output logs.
|
||||
* The baud rate for downloading is too high: lower your baud rate in the `menuconfig` menu, and try again.
|
||||
|
||||
For any technical queries, please open an [issue](https://github.com/espressif/ESP8266_RTOS_SDK/issues) on GitHub. We will get back to you soon.
|
3
examples/peripherals/i2s/main/component.mk
Normal file
3
examples/peripherals/i2s/main/component.mk
Normal file
@ -0,0 +1,3 @@
|
||||
#
|
||||
# Main Makefile. This is basically the same as a component makefile.
|
||||
#
|
114
examples/peripherals/i2s/main/i2s_example_main.c
Normal file
114
examples/peripherals/i2s/main/i2s_example_main.c
Normal file
@ -0,0 +1,114 @@
|
||||
/* I2S Example
|
||||
This example code will output 100Hz sine wave and triangle wave to 2-channel of I2S driver
|
||||
Every 5 seconds, it will change bits_per_sample [16, 24, 32] for i2s data
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "driver/i2s.h"
|
||||
#include "esp_system.h"
|
||||
#include "esp8266/pin_mux_register.h"
|
||||
|
||||
#define SAMPLE_RATE (36000)
|
||||
#define I2S_NUM (0)
|
||||
#define WAVE_FREQ_HZ (100)
|
||||
#define PI (3.14159265)
|
||||
#define I2S_MCLK_EN (1)
|
||||
#define I2S_BCK_EN (1)
|
||||
#define I2S_WS_EN (1)
|
||||
#define I2S_DO_EN (1)
|
||||
#define I2S_DI_EN (0)
|
||||
|
||||
#define SAMPLE_PER_CYCLE (SAMPLE_RATE/WAVE_FREQ_HZ)
|
||||
|
||||
static void setup_triangle_sine_waves(int bits)
|
||||
{
|
||||
int *samples_data = malloc(((bits + 8) / 16) * SAMPLE_PER_CYCLE * 4);
|
||||
unsigned int i, sample_val;
|
||||
double sin_float, triangle_float, triangle_step = (double) pow(2, bits) / SAMPLE_PER_CYCLE;
|
||||
size_t i2s_bytes_write = 0;
|
||||
|
||||
printf("\r\nTest bits=%d free mem=%d, written data=%d\n", bits, esp_get_free_heap_size(), ((bits + 8) / 16)*SAMPLE_PER_CYCLE * 4);
|
||||
|
||||
triangle_float = -(pow(2, bits) / 2 - 1);
|
||||
|
||||
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 *= (pow(2, bits) / 2 - 1);
|
||||
|
||||
if (bits == 16) {
|
||||
sample_val = 0;
|
||||
sample_val += (short)triangle_float;
|
||||
sample_val = sample_val << 16;
|
||||
sample_val += (short) sin_float;
|
||||
samples_data[i] = sample_val;
|
||||
} else if (bits == 24) { //1-bytes unused
|
||||
samples_data[i * 2] = ((int) triangle_float) << 8;
|
||||
samples_data[i * 2 + 1] = ((int) sin_float) << 8;
|
||||
} else {
|
||||
samples_data[i * 2] = ((int) triangle_float);
|
||||
samples_data[i * 2 + 1] = ((int) sin_float);
|
||||
}
|
||||
}
|
||||
|
||||
i2s_set_clk(I2S_NUM, SAMPLE_RATE, bits, 2);
|
||||
i2s_write(I2S_NUM, samples_data, ((bits + 8) / 16)*SAMPLE_PER_CYCLE * 4, &i2s_bytes_write, 100);
|
||||
|
||||
free(samples_data);
|
||||
}
|
||||
|
||||
void app_main()
|
||||
{
|
||||
// for 36Khz sample rates, we create 100Hz sine wave, every cycle need 36000/100 = 360 samples (4-bytes or 8-bytes each sample)
|
||||
// depend on bits_per_sample
|
||||
// using 6 buffers, we need 60-samples per buffer
|
||||
// if 2-channels, 16-bit each channel, total buffer is 360*4 = 1440 bytes
|
||||
// if 2-channels, 24-bit each channel, total buffer is 360*8 = 2880 bytes
|
||||
i2s_config_t i2s_config = {
|
||||
.mode = I2S_MODE_MASTER | I2S_MODE_TX, // Only TX
|
||||
.sample_rate = SAMPLE_RATE,
|
||||
.bits_per_sample = 16,
|
||||
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, // 2-channels
|
||||
.communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB,
|
||||
.dma_buf_count = 6,
|
||||
.dma_buf_len = 60
|
||||
};
|
||||
i2s_pin_config_t pin_config = {
|
||||
.bck_o_en = I2S_BCK_EN,
|
||||
.ws_o_en = I2S_WS_EN,
|
||||
.data_out_en = I2S_DO_EN,
|
||||
.data_in_en = I2S_DI_EN
|
||||
};
|
||||
|
||||
i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL);
|
||||
i2s_set_pin(I2S_NUM, &pin_config);
|
||||
|
||||
if (I2S_MCLK_EN) {
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO4_U, FUNC_CLK_XTAL);
|
||||
}
|
||||
|
||||
int test_bits = 16;
|
||||
|
||||
while (1) {
|
||||
setup_triangle_sine_waves(test_bits);
|
||||
vTaskDelay(5000 / portTICK_RATE_MS);
|
||||
test_bits += 8;
|
||||
|
||||
if (test_bits > 24) {
|
||||
test_bits = 16;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user