6ffbfbc0f6ac3464f2e9ba4646228ab81a35f5b9
Chip-cn-dat/Heroic-dat/HT517-dat/2026-07-25-15-22-41.png
| ... | ... | Binary files /dev/null and b/Chip-cn-dat/Heroic-dat/HT517-dat/2026-07-25-15-22-41.png differ |
Chip-cn-dat/Heroic-dat/HT517-dat/2026-07-25-15-23-04.png
| ... | ... | Binary files /dev/null and b/Chip-cn-dat/Heroic-dat/HT517-dat/2026-07-25-15-23-04.png differ |
Chip-cn-dat/Heroic-dat/HT517-dat/2026-07-25-15-23-27.png
| ... | ... | Binary files /dev/null and b/Chip-cn-dat/Heroic-dat/HT517-dat/2026-07-25-15-23-27.png differ |
Chip-cn-dat/Heroic-dat/HT517-dat/HT517-dat.md
| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | + |
|
| 2 | + |
|
| 3 | +# HT517-dat |
|
| 4 | + |
|
| 5 | +- [[HT517-dat]] - [[heroic-dat]] - [[speaker-I2S-dat]] |
|
| 6 | + |
|
| 7 | + |
|
| 8 | + |
|
| 9 | +## Info |
|
| 10 | + |
|
| 11 | + |
|
| 12 | + |
|
| 13 | + |
|
| 14 | + |
|
| 15 | + |
|
| 16 | + |
|
| 17 | + |
|
| 18 | + |
|
| 19 | +- DI0 - BCLK |
|
| 20 | +- DI1 - LRCK - WS |
|
| 21 | +- ID2 - DOUT - |
|
| 22 | +- EN |
|
| 23 | +- VDD |
|
| 24 | + |
|
| 25 | + |
|
| 26 | + |
|
| 27 | +## ref |
|
| 28 | + |
Chip-cn-dat/Heroic-dat/heroic-dat.md
| ... | ... | @@ -6,3 +6,13 @@ |
| 6 | 6 | |
| 7 | 7 | - [[HT7181-dat]] - [[dcdc-boost-dat]] - [[heroic-dat]]
|
| 8 | 8 | |
| 9 | +- [[HT517-dat]] - [[heroic-dat]] - [[speaker-I2S-dat]]
|
|
| 10 | +
|
|
| 11 | +
|
|
| 12 | +
|
|
| 13 | +
|
|
| 14 | +
|
|
| 15 | +
|
|
| 16 | +## ref
|
|
| 17 | +
|
|
| 18 | +
|
Chip-cn-dat/everest-semi-dat/ES8311-dat/ES8311-SDK-dat/ES8311-SDK-dat.md
| ... | ... | @@ -1,6 +1,10 @@ |
| 1 | 1 | # ES8311-SDK-dat |
| 2 | 2 | |
| 3 | 3 | |
| 4 | + |
|
| 5 | +- [[I2S-speaker-microphone-dat]] - [[ES8311-dat]] - [[ES8311-SDK-dat]] |
|
| 6 | + |
|
| 7 | + |
|
| 4 | 8 | - [[oscilloscope-dat]] |
| 5 | 9 | |
| 6 | 10 | - [[I2C-dat]] |
Chip-cn-dat/everest-semi-dat/ES8311-dat/ES8311-SDK-dat/example-2/es8311.c
| ... | ... | @@ -0,0 +1,749 @@ |
| 1 | +/* |
|
| 2 | + * ESPRESSIF MIT License |
|
| 3 | + * |
|
| 4 | + * Copyright (c) 2019 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD> |
|
| 5 | + * |
|
| 6 | + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, |
|
| 7 | + * it is free of charge, to any person obtaining a copy of this software and associated |
|
| 8 | + * documentation files (the "Software"), to deal in the Software without restriction, including |
|
| 9 | + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
| 10 | + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished |
|
| 11 | + * to do so, subject to the following conditions: |
|
| 12 | + * |
|
| 13 | + * The above copyright notice and this permission notice shall be included in all copies or |
|
| 14 | + * substantial portions of the Software. |
|
| 15 | + * |
|
| 16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
| 17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
|
| 18 | + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
| 19 | + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
|
| 20 | + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
| 21 | + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
| 22 | + * |
|
| 23 | + */ |
|
| 24 | + |
|
| 25 | +#include <string.h> |
|
| 26 | +#include "driver/i2c.h" |
|
| 27 | +#include "board.h" |
|
| 28 | +#include "esp_log.h" |
|
| 29 | +#include "es8311.h" |
|
| 30 | + |
|
| 31 | +/* ES8311 address |
|
| 32 | + * 0x32:CE=1;0x30:CE=0 |
|
| 33 | + */ |
|
| 34 | +#define ES8311_ADDR 0x30 |
|
| 35 | + |
|
| 36 | +/* |
|
| 37 | + * to define the clock soure of MCLK |
|
| 38 | + */ |
|
| 39 | +#define FROM_MCLK_PIN 0 |
|
| 40 | +#define FROM_SCLK_PIN 1 |
|
| 41 | +#define MCLK_SOURCE 0 |
|
| 42 | + |
|
| 43 | +/* |
|
| 44 | + * to define whether to reverse the clock |
|
| 45 | + */ |
|
| 46 | +#define INVERT_MCLK 0 // do not invert |
|
| 47 | +#define INVERT_SCLK 0 |
|
| 48 | + |
|
| 49 | +#define IS_DMIC 0 // Is it a digital microphone |
|
| 50 | + |
|
| 51 | +#define MCLK_DIV_FRE 256 |
|
| 52 | + |
|
| 53 | +/* |
|
| 54 | + * i2c default configuration |
|
| 55 | + */ |
|
| 56 | +static i2c_config_t es_i2c_cfg = { |
|
| 57 | + .mode = I2C_MODE_MASTER, |
|
| 58 | + .sda_pullup_en = GPIO_PULLUP_ENABLE, |
|
| 59 | + .scl_pullup_en = GPIO_PULLUP_ENABLE, |
|
| 60 | + .master.clk_speed = 100000 |
|
| 61 | +}; |
|
| 62 | + |
|
| 63 | +/* |
|
| 64 | + * operate function of codec |
|
| 65 | + */ |
|
| 66 | +audio_hal_func_t AUDIO_CODEC_ES8311_DEFAULT_HANDLE = { |
|
| 67 | + .audio_codec_initialize = es8311_codec_init, |
|
| 68 | + .audio_codec_deinitialize = es8311_codec_deinit, |
|
| 69 | + .audio_codec_ctrl = es8311_codec_ctrl_state, |
|
| 70 | + .audio_codec_config_iface = es8311_codec_config_i2s, |
|
| 71 | + .audio_codec_set_mute = es8311_set_voice_mute, |
|
| 72 | + .audio_codec_set_volume = es8311_codec_set_voice_volume, |
|
| 73 | + .audio_codec_get_volume = es8311_codec_get_voice_volume, |
|
| 74 | +}; |
|
| 75 | + |
|
| 76 | +/* |
|
| 77 | + * Clock coefficient structer |
|
| 78 | + */ |
|
| 79 | +struct _coeff_div { |
|
| 80 | + uint32_t mclk; /* mclk frequency */ |
|
| 81 | + uint32_t rate; /* sample rate */ |
|
| 82 | + uint8_t pre_div; /* the pre divider with range from 1 to 8 */ |
|
| 83 | + uint8_t pre_multi; /* the pre multiplier with x1, x2, x4 and x8 selection */ |
|
| 84 | + uint8_t adc_div; /* adcclk divider */ |
|
| 85 | + uint8_t dac_div; /* dacclk divider */ |
|
| 86 | + uint8_t fs_mode; /* double speed or single speed, =0, ss, =1, ds */ |
|
| 87 | + uint8_t lrck_h; /* adclrck divider and daclrck divider */ |
|
| 88 | + uint8_t lrck_l; |
|
| 89 | + uint8_t bclk_div; /* sclk divider */ |
|
| 90 | + uint8_t adc_osr; /* adc osr */ |
|
| 91 | + uint8_t dac_osr; /* dac osr */ |
|
| 92 | +}; |
|
| 93 | + |
|
| 94 | +/* codec hifi mclk clock divider coefficients */ |
|
| 95 | +static const struct _coeff_div coeff_div[] = { |
|
| 96 | + //mclk rate pre_div mult adc_div dac_div fs_mode lrch lrcl bckdiv osr |
|
| 97 | + /* 8k */ |
|
| 98 | + {12288000, 8000 , 0x06, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 99 | + {18432000, 8000 , 0x03, 0x02, 0x03, 0x03, 0x00, 0x05, 0xff, 0x18, 0x10, 0x10}, |
|
| 100 | + {16384000, 8000 , 0x08, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 101 | + {8192000 , 8000 , 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 102 | + {6144000 , 8000 , 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 103 | + {4096000 , 8000 , 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 104 | + {3072000 , 8000 , 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 105 | + {2048000 , 8000 , 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 106 | + {1536000 , 8000 , 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 107 | + {1024000 , 8000 , 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 108 | + |
|
| 109 | + /* 11.025k */ |
|
| 110 | + {11289600, 11025, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 111 | + {5644800 , 11025, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 112 | + {2822400 , 11025, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 113 | + {1411200 , 11025, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 114 | + |
|
| 115 | + /* 12k */ |
|
| 116 | + {12288000, 12000, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 117 | + {6144000 , 12000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 118 | + {3072000 , 12000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 119 | + {1536000 , 12000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 120 | + |
|
| 121 | + /* 16k */ |
|
| 122 | + {12288000, 16000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 123 | + {18432000, 16000, 0x03, 0x02, 0x03, 0x03, 0x00, 0x02, 0xff, 0x0c, 0x10, 0x10}, |
|
| 124 | + {16384000, 16000, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 125 | + {8192000 , 16000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 126 | + {6144000 , 16000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 127 | + {4096000 , 16000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 128 | + {3072000 , 16000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 129 | + {2048000 , 16000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 130 | + {1536000 , 16000, 0x03, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 131 | + {1024000 , 16000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 132 | + |
|
| 133 | + /* 22.05k */ |
|
| 134 | + {11289600, 22050, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 135 | + {5644800 , 22050, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 136 | + {2822400 , 22050, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 137 | + {1411200 , 22050, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 138 | + |
|
| 139 | + /* 24k */ |
|
| 140 | + {12288000, 24000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 141 | + {18432000, 24000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 142 | + {6144000 , 24000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 143 | + {3072000 , 24000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 144 | + {1536000 , 24000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 145 | + |
|
| 146 | + /* 32k */ |
|
| 147 | + {12288000, 32000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 148 | + {18432000, 32000, 0x03, 0x04, 0x03, 0x03, 0x00, 0x02, 0xff, 0x0c, 0x10, 0x10}, |
|
| 149 | + {16384000, 32000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 150 | + {8192000 , 32000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 151 | + {6144000 , 32000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 152 | + {4096000 , 32000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 153 | + {3072000 , 32000, 0x03, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 154 | + {2048000 , 32000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 155 | + {1536000 , 32000, 0x03, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, |
|
| 156 | + {1024000 , 32000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 157 | + |
|
| 158 | + /* 44.1k */ |
|
| 159 | + {11289600, 44100, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 160 | + {5644800 , 44100, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 161 | + {2822400 , 44100, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 162 | + {1411200 , 44100, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 163 | + |
|
| 164 | + /* 48k */ |
|
| 165 | + {12288000, 48000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 166 | + {18432000, 48000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 167 | + {6144000 , 48000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 168 | + {3072000 , 48000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 169 | + {1536000 , 48000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 170 | + |
|
| 171 | + /* 64k */ |
|
| 172 | + {12288000, 64000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 173 | + {18432000, 64000, 0x03, 0x04, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10}, |
|
| 174 | + {16384000, 64000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 175 | + {8192000 , 64000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 176 | + {6144000 , 64000, 0x01, 0x04, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10}, |
|
| 177 | + {4096000 , 64000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 178 | + {3072000 , 64000, 0x01, 0x08, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10}, |
|
| 179 | + {2048000 , 64000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 180 | + {1536000 , 64000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0xbf, 0x03, 0x18, 0x18}, |
|
| 181 | + {1024000 , 64000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, |
|
| 182 | + |
|
| 183 | + /* 88.2k */ |
|
| 184 | + {11289600, 88200, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 185 | + {5644800 , 88200, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 186 | + {2822400 , 88200, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 187 | + {1411200 , 88200, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, |
|
| 188 | + |
|
| 189 | + /* 96k */ |
|
| 190 | + {12288000, 96000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 191 | + {18432000, 96000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 192 | + {6144000 , 96000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 193 | + {3072000 , 96000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 194 | + {1536000 , 96000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, |
|
| 195 | +}; |
|
| 196 | + |
|
| 197 | +static char *TAG = "DRV8311"; |
|
| 198 | + |
|
| 199 | +#define ES_ASSERT(a, format, b, ...) \ |
|
| 200 | + if ((a) != 0) { \ |
|
| 201 | + ESP_LOGE(TAG, format, ##__VA_ARGS__); \ |
|
| 202 | + return b;\ |
|
| 203 | + } |
|
| 204 | + |
|
| 205 | +static int es8311_write_reg(uint8_t reg_addr, uint8_t data) |
|
| 206 | +{ |
|
| 207 | + int res = 0; |
|
| 208 | + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); |
|
| 209 | + res |= i2c_master_start(cmd); |
|
| 210 | + res |= i2c_master_write_byte(cmd, ES8311_ADDR, 1 /*ACK_CHECK_EN*/); |
|
| 211 | + res |= i2c_master_write_byte(cmd, reg_addr, 1 /*ACK_CHECK_EN*/); |
|
| 212 | + res |= i2c_master_write_byte(cmd, data, 1 /*ACK_CHECK_EN*/); |
|
| 213 | + res |= i2c_master_stop(cmd); |
|
| 214 | + res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_RATE_MS); |
|
| 215 | + i2c_cmd_link_delete(cmd); |
|
| 216 | + ES_ASSERT(res, "Es8311 Write Reg error", -1); |
|
| 217 | + return res; |
|
| 218 | +} |
|
| 219 | + |
|
| 220 | +static int es8311_read_reg(uint8_t reg_addr) |
|
| 221 | +{ |
|
| 222 | + uint8_t data; |
|
| 223 | + int res = 0; |
|
| 224 | + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); |
|
| 225 | + |
|
| 226 | + res |= i2c_master_start(cmd); |
|
| 227 | + res |= i2c_master_write_byte(cmd, ES8311_ADDR, 1 /*ACK_CHECK_EN*/); |
|
| 228 | + res |= i2c_master_write_byte(cmd, reg_addr, 1 /*ACK_CHECK_EN*/); |
|
| 229 | + res |= i2c_master_stop(cmd); |
|
| 230 | + res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_RATE_MS); |
|
| 231 | + i2c_cmd_link_delete(cmd); |
|
| 232 | + |
|
| 233 | + cmd = i2c_cmd_link_create(); |
|
| 234 | + res |= i2c_master_start(cmd); |
|
| 235 | + res |= i2c_master_write_byte(cmd, ES8311_ADDR | 0x01, 1 /*ACK_CHECK_EN*/); |
|
| 236 | + res |= i2c_master_read_byte(cmd, &data, 0x01 /*NACK_VAL*/); |
|
| 237 | + res |= i2c_master_stop(cmd); |
|
| 238 | + res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_RATE_MS); |
|
| 239 | + i2c_cmd_link_delete(cmd); |
|
| 240 | + |
|
| 241 | + ES_ASSERT(res, "Es8311 Read Reg error", -1); |
|
| 242 | + return (int)data; |
|
| 243 | +} |
|
| 244 | + |
|
| 245 | +static int i2c_init() |
|
| 246 | +{ |
|
| 247 | + int res = 0; |
|
| 248 | + get_i2c_pins(I2C_NUM_0, &es_i2c_cfg); |
|
| 249 | + res |= i2c_param_config(I2C_NUM_0, &es_i2c_cfg); |
|
| 250 | + res |= i2c_driver_install(I2C_NUM_0, es_i2c_cfg.mode, 0, 0, 0); |
|
| 251 | + ES_ASSERT(res, "i2c_init error", -1); |
|
| 252 | + return res; |
|
| 253 | +} |
|
| 254 | + |
|
| 255 | +/* |
|
| 256 | +* look for the coefficient in coeff_div[] table |
|
| 257 | +*/ |
|
| 258 | +static int get_coeff(uint32_t mclk, uint32_t rate) |
|
| 259 | +{ |
|
| 260 | + for (int i = 0; i < (sizeof(coeff_div) / sizeof(coeff_div[0])); i++) { |
|
| 261 | + if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) |
|
| 262 | + return i; |
|
| 263 | + } |
|
| 264 | + return -1; |
|
| 265 | +} |
|
| 266 | + |
|
| 267 | +/* |
|
| 268 | +* set es8311 dac mute or not |
|
| 269 | +* if mute = 0, dac un-mute |
|
| 270 | +* if mute = 1, dac mute |
|
| 271 | +*/ |
|
| 272 | +static void es8311_mute(int mute) |
|
| 273 | +{ |
|
| 274 | + uint8_t regv; |
|
| 275 | + ESP_LOGI(TAG, "Enter into es8311_mute(), mute = %d\n", mute); |
|
| 276 | + regv = es8311_read_reg(ES8311_DAC_REG31) & 0x9f; |
|
| 277 | + if (mute) { |
|
| 278 | + es8311_write_reg(ES8311_SYSTEM_REG12, 0x02); |
|
| 279 | + es8311_write_reg(ES8311_DAC_REG31, regv | 0x60); |
|
| 280 | + es8311_write_reg(ES8311_DAC_REG32, 0x00); |
|
| 281 | + es8311_write_reg(ES8311_DAC_REG37, 0x08); |
|
| 282 | + } else { |
|
| 283 | + es8311_write_reg(ES8311_DAC_REG31, regv); |
|
| 284 | + es8311_write_reg(ES8311_SYSTEM_REG12, 0x00); |
|
| 285 | + } |
|
| 286 | +} |
|
| 287 | + |
|
| 288 | +/* |
|
| 289 | +* set es8311 into suspend mode |
|
| 290 | +*/ |
|
| 291 | +static void es8311_suspend(void) |
|
| 292 | +{ |
|
| 293 | + ESP_LOGI(TAG, "Enter into es8311_suspend()"); |
|
| 294 | + es8311_write_reg(ES8311_DAC_REG32, 0x00); |
|
| 295 | + es8311_write_reg(ES8311_ADC_REG17, 0x00); |
|
| 296 | + es8311_write_reg(ES8311_SYSTEM_REG0E, 0xFF); |
|
| 297 | + es8311_write_reg(ES8311_SYSTEM_REG12, 0x02); |
|
| 298 | + es8311_write_reg(ES8311_SYSTEM_REG14, 0x00); |
|
| 299 | + es8311_write_reg(ES8311_SYSTEM_REG0D, 0xFA); |
|
| 300 | + es8311_write_reg(ES8311_ADC_REG15, 0x00); |
|
| 301 | + es8311_write_reg(ES8311_DAC_REG37, 0x08); |
|
| 302 | + es8311_write_reg(ES8311_GP_REG45, 0x01); |
|
| 303 | +} |
|
| 304 | + |
|
| 305 | +/* |
|
| 306 | +* enable pa power |
|
| 307 | +*/ |
|
| 308 | +void es8311_pa_power(bool enable) |
|
| 309 | +{ |
|
| 310 | + gpio_config_t io_conf; |
|
| 311 | + memset(&io_conf, 0, sizeof(io_conf)); |
|
| 312 | + io_conf.intr_type = GPIO_PIN_INTR_DISABLE; |
|
| 313 | + io_conf.mode = GPIO_MODE_OUTPUT; |
|
| 314 | + io_conf.pin_bit_mask = BIT(get_pa_enable_gpio()); |
|
| 315 | + io_conf.pull_down_en = 0; |
|
| 316 | + io_conf.pull_up_en = 0; |
|
| 317 | + gpio_config(&io_conf); |
|
| 318 | + if (enable) { |
|
| 319 | + gpio_set_level(get_pa_enable_gpio(), 1); |
|
| 320 | + } else { |
|
| 321 | + gpio_set_level(get_pa_enable_gpio(), 0); |
|
| 322 | + } |
|
| 323 | +} |
|
| 324 | + |
|
| 325 | +esp_err_t es8311_codec_init(audio_hal_codec_config_t *codec_cfg) |
|
| 326 | +{ |
|
| 327 | + uint8_t datmp, regv; |
|
| 328 | + int coeff; |
|
| 329 | + esp_err_t ret = ESP_OK; |
|
| 330 | + i2c_init(); // ESP32 in master mode |
|
| 331 | + |
|
| 332 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, 0x30); |
|
| 333 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, 0x00); |
|
| 334 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG03, 0x10); |
|
| 335 | + ret |= es8311_write_reg(ES8311_ADC_REG16, 0x24); |
|
| 336 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG04, 0x10); |
|
| 337 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG05, 0x00); |
|
| 338 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG0B, 0x00); |
|
| 339 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG0C, 0x00); |
|
| 340 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG10, 0x1F); |
|
| 341 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG11, 0x7F); |
|
| 342 | + ret |= es8311_write_reg(ES8311_RESET_REG00, 0x80); |
|
| 343 | + /* |
|
| 344 | + * Set Codec into Master or Slave mode |
|
| 345 | + */ |
|
| 346 | + regv = es8311_read_reg(ES8311_RESET_REG00); |
|
| 347 | + /* |
|
| 348 | + * Set master/slave audio interface |
|
| 349 | + */ |
|
| 350 | + audio_hal_codec_i2s_iface_t *i2s_cfg = &(codec_cfg->i2s_iface); |
|
| 351 | + switch (i2s_cfg->mode) { |
|
| 352 | + case AUDIO_HAL_MODE_MASTER: /* MASTER MODE */ |
|
| 353 | + ESP_LOGI(TAG, "ES8311 in Master mode"); |
|
| 354 | + regv |= 0x40; |
|
| 355 | + break; |
|
| 356 | + case AUDIO_HAL_MODE_SLAVE: /* SLAVE MODE */ |
|
| 357 | + ESP_LOGI(TAG, "ES8311 in Slave mode"); |
|
| 358 | + regv &= 0xBF; |
|
| 359 | + break; |
|
| 360 | + default: |
|
| 361 | + regv &= 0xBF; |
|
| 362 | + } |
|
| 363 | + ret |= es8311_write_reg(ES8311_RESET_REG00, regv); |
|
| 364 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, 0x3F); |
|
| 365 | + /* |
|
| 366 | + * Select clock source for internal mclk |
|
| 367 | + */ |
|
| 368 | + switch (MCLK_SOURCE) { |
|
| 369 | + case FROM_MCLK_PIN: |
|
| 370 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); |
|
| 371 | + regv &= 0x7F; |
|
| 372 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); |
|
| 373 | + break; |
|
| 374 | + case FROM_SCLK_PIN: |
|
| 375 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); |
|
| 376 | + regv |= 0x80; |
|
| 377 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); |
|
| 378 | + break; |
|
| 379 | + default: |
|
| 380 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); |
|
| 381 | + regv &= 0x7F; |
|
| 382 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); |
|
| 383 | + break; |
|
| 384 | + } |
|
| 385 | + int sample_fre = 0; |
|
| 386 | + int mclk_fre = 0; |
|
| 387 | + switch (i2s_cfg->samples) { |
|
| 388 | + case AUDIO_HAL_08K_SAMPLES: |
|
| 389 | + sample_fre = 8000; |
|
| 390 | + break; |
|
| 391 | + case AUDIO_HAL_11K_SAMPLES: |
|
| 392 | + sample_fre = 11025; |
|
| 393 | + break; |
|
| 394 | + case AUDIO_HAL_16K_SAMPLES: |
|
| 395 | + sample_fre = 16000; |
|
| 396 | + break; |
|
| 397 | + case AUDIO_HAL_22K_SAMPLES: |
|
| 398 | + sample_fre = 22050; |
|
| 399 | + break; |
|
| 400 | + case AUDIO_HAL_24K_SAMPLES: |
|
| 401 | + sample_fre = 24000; |
|
| 402 | + break; |
|
| 403 | + case AUDIO_HAL_32K_SAMPLES: |
|
| 404 | + sample_fre = 32000; |
|
| 405 | + break; |
|
| 406 | + case AUDIO_HAL_44K_SAMPLES: |
|
| 407 | + sample_fre = 44100; |
|
| 408 | + break; |
|
| 409 | + case AUDIO_HAL_48K_SAMPLES: |
|
| 410 | + sample_fre = 48000; |
|
| 411 | + break; |
|
| 412 | + default: |
|
| 413 | + ESP_LOGE(TAG, "Unable to configure sample rate %dHz", sample_fre); |
|
| 414 | + break; |
|
| 415 | + } |
|
| 416 | + mclk_fre = sample_fre * MCLK_DIV_FRE; |
|
| 417 | + coeff = get_coeff(mclk_fre, sample_fre); |
|
| 418 | + if (coeff < 0) { |
|
| 419 | + ESP_LOGE(TAG, "Unable to configure sample rate %dHz with %dHz MCLK", sample_fre, mclk_fre); |
|
| 420 | + return ESP_FAIL; |
|
| 421 | + } |
|
| 422 | + /* |
|
| 423 | + * Set clock parammeters |
|
| 424 | + */ |
|
| 425 | + if (coeff >= 0) { |
|
| 426 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG02) & 0x07; |
|
| 427 | + regv |= (coeff_div[coeff].pre_div - 1) << 5; |
|
| 428 | + datmp = 0; |
|
| 429 | + switch (coeff_div[coeff].pre_multi) { |
|
| 430 | + case 1: |
|
| 431 | + datmp = 0; |
|
| 432 | + break; |
|
| 433 | + case 2: |
|
| 434 | + datmp = 1; |
|
| 435 | + break; |
|
| 436 | + case 4: |
|
| 437 | + datmp = 2; |
|
| 438 | + break; |
|
| 439 | + case 8: |
|
| 440 | + datmp = 3; |
|
| 441 | + break; |
|
| 442 | + default: |
|
| 443 | + break; |
|
| 444 | + } |
|
| 445 | + regv |= (datmp) << 3; |
|
| 446 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, regv); |
|
| 447 | + |
|
| 448 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG05) & 0x00; |
|
| 449 | + regv |= (coeff_div[coeff].adc_div - 1) << 4; |
|
| 450 | + regv |= (coeff_div[coeff].dac_div - 1) << 0; |
|
| 451 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG05, regv); |
|
| 452 | + |
|
| 453 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG03) & 0x80; |
|
| 454 | + regv |= coeff_div[coeff].fs_mode << 6; |
|
| 455 | + regv |= coeff_div[coeff].adc_osr << 0; |
|
| 456 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG03, regv); |
|
| 457 | + |
|
| 458 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG04) & 0x80; |
|
| 459 | + regv |= coeff_div[coeff].dac_osr << 0; |
|
| 460 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG04, regv); |
|
| 461 | + |
|
| 462 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG07) & 0xC0; |
|
| 463 | + regv |= coeff_div[coeff].lrck_h << 0; |
|
| 464 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG07, regv); |
|
| 465 | + |
|
| 466 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG08) & 0x00; |
|
| 467 | + regv |= coeff_div[coeff].lrck_l << 0; |
|
| 468 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG08, regv); |
|
| 469 | + |
|
| 470 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG06) & 0xE0; |
|
| 471 | + if (coeff_div[coeff].bclk_div < 19) { |
|
| 472 | + regv |= (coeff_div[coeff].bclk_div - 1) << 0; |
|
| 473 | + } else { |
|
| 474 | + regv |= (coeff_div[coeff].bclk_div) << 0; |
|
| 475 | + } |
|
| 476 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG06, regv); |
|
| 477 | + } |
|
| 478 | + |
|
| 479 | + /* |
|
| 480 | + * mclk inverted or not |
|
| 481 | + */ |
|
| 482 | + if (INVERT_MCLK) { |
|
| 483 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); |
|
| 484 | + regv |= 0x40; |
|
| 485 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); |
|
| 486 | + } else { |
|
| 487 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); |
|
| 488 | + regv &= ~(0x40); |
|
| 489 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); |
|
| 490 | + } |
|
| 491 | + /* |
|
| 492 | + * sclk inverted or not |
|
| 493 | + */ |
|
| 494 | + if (INVERT_SCLK) { |
|
| 495 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG06); |
|
| 496 | + regv |= 0x20; |
|
| 497 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG06, regv); |
|
| 498 | + } else { |
|
| 499 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG06); |
|
| 500 | + regv &= ~(0x20); |
|
| 501 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG06, regv); |
|
| 502 | + } |
|
| 503 | + |
|
| 504 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG13, 0x10); |
|
| 505 | + ret |= es8311_write_reg(ES8311_ADC_REG1B, 0x0A); |
|
| 506 | + ret |= es8311_write_reg(ES8311_ADC_REG1C, 0x6A); |
|
| 507 | + ret |= es8311_write_reg(ES8311_GPIO_REG44, 0x08); |
|
| 508 | + |
|
| 509 | + es8311_pa_power(true); |
|
| 510 | + return ESP_OK; |
|
| 511 | +} |
|
| 512 | + |
|
| 513 | +esp_err_t es8311_codec_deinit() |
|
| 514 | +{ |
|
| 515 | +//TODO |
|
| 516 | + return ESP_OK; |
|
| 517 | +} |
|
| 518 | + |
|
| 519 | +esp_err_t es8311_config_fmt(es_i2s_fmt_t fmt) |
|
| 520 | +{ |
|
| 521 | + esp_err_t ret = ESP_OK; |
|
| 522 | + uint8_t adc_iface = 0, dac_iface = 0; |
|
| 523 | + dac_iface = es8311_read_reg(ES8311_SDPIN_REG09); |
|
| 524 | + adc_iface = es8311_read_reg(ES8311_SDPOUT_REG0A); |
|
| 525 | + switch (fmt) { |
|
| 526 | + case AUDIO_HAL_I2S_NORMAL: |
|
| 527 | + ESP_LOGD(TAG, "ES8311 in I2S Format"); |
|
| 528 | + dac_iface &= 0xFC; |
|
| 529 | + adc_iface &= 0xFC; |
|
| 530 | + break; |
|
| 531 | + case AUDIO_HAL_I2S_LEFT: |
|
| 532 | + case AUDIO_HAL_I2S_RIGHT: |
|
| 533 | + ESP_LOGD(TAG, "ES8311 in LJ Format"); |
|
| 534 | + adc_iface &= 0xFC; |
|
| 535 | + dac_iface &= 0xFC; |
|
| 536 | + adc_iface |= 0x01; |
|
| 537 | + dac_iface |= 0x01; |
|
| 538 | + break; |
|
| 539 | + case AUDIO_HAL_I2S_DSP: |
|
| 540 | + ESP_LOGD(TAG, "ES8311 in DSP-A Format"); |
|
| 541 | + adc_iface &= 0xDC; |
|
| 542 | + dac_iface &= 0xDC; |
|
| 543 | + adc_iface |= 0x03; |
|
| 544 | + dac_iface |= 0x03; |
|
| 545 | + break; |
|
| 546 | + default: |
|
| 547 | + dac_iface &= 0xFC; |
|
| 548 | + adc_iface &= 0xFC; |
|
| 549 | + break; |
|
| 550 | + } |
|
| 551 | + ret |= es8311_write_reg(ES8311_SDPIN_REG09, dac_iface); |
|
| 552 | + ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, adc_iface); |
|
| 553 | + |
|
| 554 | + return ret; |
|
| 555 | +} |
|
| 556 | + |
|
| 557 | +esp_err_t es8311_set_bits_per_sample(audio_hal_iface_bits_t bits) |
|
| 558 | +{ |
|
| 559 | + esp_err_t ret = ESP_OK; |
|
| 560 | + uint8_t adc_iface = 0, dac_iface = 0; |
|
| 561 | + dac_iface = es8311_read_reg(ES8311_SDPIN_REG09); |
|
| 562 | + adc_iface = es8311_read_reg(ES8311_SDPOUT_REG0A); |
|
| 563 | + switch (bits) { |
|
| 564 | + case AUDIO_HAL_BIT_LENGTH_16BITS: |
|
| 565 | + dac_iface |= 0x0c; |
|
| 566 | + adc_iface |= 0x0c; |
|
| 567 | + break; |
|
| 568 | + case AUDIO_HAL_BIT_LENGTH_24BITS: |
|
| 569 | + break; |
|
| 570 | + case AUDIO_HAL_BIT_LENGTH_32BITS: |
|
| 571 | + dac_iface |= 0x10; |
|
| 572 | + adc_iface |= 0x10; |
|
| 573 | + break; |
|
| 574 | + default: |
|
| 575 | + dac_iface |= 0x0c; |
|
| 576 | + adc_iface |= 0x0c; |
|
| 577 | + break; |
|
| 578 | + |
|
| 579 | + } |
|
| 580 | + ret |= es8311_write_reg(ES8311_SDPIN_REG09, dac_iface); |
|
| 581 | + ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, adc_iface); |
|
| 582 | + |
|
| 583 | + return ret; |
|
| 584 | +} |
|
| 585 | + |
|
| 586 | +esp_err_t es8311_codec_config_i2s(audio_hal_codec_mode_t mode, audio_hal_codec_i2s_iface_t *iface) |
|
| 587 | +{ |
|
| 588 | + int ret = ESP_OK; |
|
| 589 | + ret |= es8311_set_bits_per_sample(iface->bits); |
|
| 590 | + ret |= es8311_config_fmt(iface->fmt); |
|
| 591 | + return ret; |
|
| 592 | +} |
|
| 593 | + |
|
| 594 | +esp_err_t es8311_codec_ctrl_state(audio_hal_codec_mode_t mode, audio_hal_ctrl_t ctrl_state) |
|
| 595 | +{ |
|
| 596 | + esp_err_t ret = ESP_OK; |
|
| 597 | + es_module_t es_mode = ES_MODULE_MIN; |
|
| 598 | + |
|
| 599 | + switch (mode) { |
|
| 600 | + case AUDIO_HAL_CODEC_MODE_ENCODE: |
|
| 601 | + es_mode = ES_MODULE_ADC; |
|
| 602 | + break; |
|
| 603 | + case AUDIO_HAL_CODEC_MODE_LINE_IN: |
|
| 604 | + es_mode = ES_MODULE_LINE; |
|
| 605 | + break; |
|
| 606 | + case AUDIO_HAL_CODEC_MODE_DECODE: |
|
| 607 | + es_mode = ES_MODULE_DAC; |
|
| 608 | + break; |
|
| 609 | + case AUDIO_HAL_CODEC_MODE_BOTH: |
|
| 610 | + es_mode = ES_MODULE_ADC_DAC; |
|
| 611 | + break; |
|
| 612 | + default: |
|
| 613 | + es_mode = ES_MODULE_DAC; |
|
| 614 | + ESP_LOGW(TAG, "Codec mode not support, default is decode mode"); |
|
| 615 | + break; |
|
| 616 | + } |
|
| 617 | + |
|
| 618 | + if (ctrl_state == AUDIO_HAL_CTRL_START) { |
|
| 619 | + ret |= es8311_start(es_mode); |
|
| 620 | + } else { |
|
| 621 | + ESP_LOGW(TAG, "The codec is about to stop"); |
|
| 622 | + ret |= es8311_stop(es_mode); |
|
| 623 | + } |
|
| 624 | + |
|
| 625 | + return ret; |
|
| 626 | +} |
|
| 627 | + |
|
| 628 | +esp_err_t es8311_start(es_module_t mode) |
|
| 629 | +{ |
|
| 630 | + esp_err_t ret = ESP_OK; |
|
| 631 | + uint8_t adc_iface = 0, dac_iface = 0; |
|
| 632 | + |
|
| 633 | + dac_iface = es8311_read_reg(ES8311_SDPIN_REG09) & 0xBF; |
|
| 634 | + adc_iface = es8311_read_reg(ES8311_SDPOUT_REG0A) & 0xBF; |
|
| 635 | + adc_iface |= BIT(6); |
|
| 636 | + dac_iface |= BIT(6); |
|
| 637 | + |
|
| 638 | + if (mode == ES_MODULE_LINE) { |
|
| 639 | + ESP_LOGE(TAG, "The codec es8311 doesn't support ES_MODULE_LINE mode"); |
|
| 640 | + return ESP_FAIL; |
|
| 641 | + } |
|
| 642 | + if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC) { |
|
| 643 | + adc_iface &= ~(BIT(6)); |
|
| 644 | + } |
|
| 645 | + if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC) { |
|
| 646 | + dac_iface &= ~(BIT(6)); |
|
| 647 | + } |
|
| 648 | + |
|
| 649 | + ret |= es8311_write_reg(ES8311_SDPIN_REG09, dac_iface); |
|
| 650 | + ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, adc_iface); |
|
| 651 | + |
|
| 652 | + ret |= es8311_write_reg(ES8311_DAC_REG32, 0xBF); |
|
| 653 | + ret |= es8311_write_reg(ES8311_ADC_REG17, 0xBF); |
|
| 654 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG0E, 0x02); |
|
| 655 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG12, 0x00); |
|
| 656 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG14, 0x1A); |
|
| 657 | + |
|
| 658 | + /* |
|
| 659 | + * pdm dmic enable or disable |
|
| 660 | + */ |
|
| 661 | + int regv = 0; |
|
| 662 | + if (IS_DMIC) { |
|
| 663 | + regv = es8311_read_reg(ES8311_SYSTEM_REG14); |
|
| 664 | + regv |= 0x40; |
|
| 665 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG14, regv); |
|
| 666 | + } else { |
|
| 667 | + regv = es8311_read_reg(ES8311_SYSTEM_REG14); |
|
| 668 | + regv &= ~(0x40); |
|
| 669 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG14, regv); |
|
| 670 | + } |
|
| 671 | + |
|
| 672 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG0D, 0x01); |
|
| 673 | + ret |= es8311_write_reg(ES8311_ADC_REG15, 0x40); |
|
| 674 | + ret |= es8311_write_reg(ES8311_DAC_REG37, 0x48); |
|
| 675 | + ret |= es8311_write_reg(ES8311_GP_REG45, 0x00); |
|
| 676 | + |
|
| 677 | + return ret; |
|
| 678 | +} |
|
| 679 | + |
|
| 680 | +esp_err_t es8311_stop(es_module_t mode) |
|
| 681 | +{ |
|
| 682 | + esp_err_t ret = ESP_OK; |
|
| 683 | + es8311_suspend(); |
|
| 684 | + return ret; |
|
| 685 | +} |
|
| 686 | + |
|
| 687 | +int es8311_codec_set_voice_volume(int volume) |
|
| 688 | +{ |
|
| 689 | + int res = 0; |
|
| 690 | + if (volume < 0) { |
|
| 691 | + volume = 0; |
|
| 692 | + } else if (volume > 100) { |
|
| 693 | + volume = 100; |
|
| 694 | + } |
|
| 695 | + int vol = (volume) * 2550 / 1000; |
|
| 696 | + ESP_LOGD(TAG, "SET: volume:%d", vol); |
|
| 697 | + es8311_write_reg(ES8311_DAC_REG32, vol); |
|
| 698 | + return res; |
|
| 699 | +} |
|
| 700 | + |
|
| 701 | +int es8311_codec_get_voice_volume(int *volume) |
|
| 702 | +{ |
|
| 703 | + int res = ESP_OK; |
|
| 704 | + int regv = 0; |
|
| 705 | + regv = es8311_read_reg(ES8311_DAC_REG32); |
|
| 706 | + if (regv == ESP_FAIL) { |
|
| 707 | + *volume = 0; |
|
| 708 | + res = ESP_FAIL; |
|
| 709 | + } else { |
|
| 710 | + *volume = regv * 100 / 256; |
|
| 711 | + } |
|
| 712 | + ESP_LOGD(TAG, "GET: res:%d, volume:%d", regv, *volume); |
|
| 713 | + return res; |
|
| 714 | +} |
|
| 715 | + |
|
| 716 | +esp_err_t es8311_set_voice_mute(bool enable) |
|
| 717 | +{ |
|
| 718 | + int res = 0; |
|
| 719 | + ESP_LOGD(TAG, "Es8311SetVoiceMute volume:%d", enable); |
|
| 720 | + es8311_mute(enable); |
|
| 721 | + return res; |
|
| 722 | +} |
|
| 723 | + |
|
| 724 | +int es8311_get_voice_mute(int *mute) |
|
| 725 | +{ |
|
| 726 | + int res = -1; |
|
| 727 | + uint8_t reg = 0; |
|
| 728 | + res = es8311_read_reg(ES8311_DAC_REG31); |
|
| 729 | + if (res != ESP_FAIL) { |
|
| 730 | + reg = (res & 0x20) >> 5; |
|
| 731 | + } |
|
| 732 | + *mute = reg; |
|
| 733 | + return res; |
|
| 734 | +} |
|
| 735 | + |
|
| 736 | +esp_err_t es8311_set_mic_gain(es8311_mic_gain_t gain_db) |
|
| 737 | +{ |
|
| 738 | + int res = 0; |
|
| 739 | + res = es8311_write_reg(ES8311_ADC_REG16, gain_db); // MIC gain scale |
|
| 740 | + return res; |
|
| 741 | +} |
|
| 742 | + |
|
| 743 | +void es8311_read_all() |
|
| 744 | +{ |
|
| 745 | + for (int i = 0; i < 0x4A; i++) { |
|
| 746 | + uint8_t reg = es8311_read_reg(i); |
|
| 747 | + ets_printf("REG:%02x, %02x\n", reg, i); |
|
| 748 | + } |
|
| 749 | +} |
Chip-cn-dat/everest-semi-dat/ES8311-dat/ES8311-SDK-dat/example-2/es8311.h
| ... | ... | @@ -0,0 +1,237 @@ |
| 1 | +/* |
|
| 2 | + * ESPRESSIF MIT License |
|
| 3 | + * |
|
| 4 | + * Copyright (c) 2019 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD> |
|
| 5 | + * |
|
| 6 | + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, |
|
| 7 | + * it is free of charge, to any person obtaining a copy of this software and associated |
|
| 8 | + * documentation files (the "Software"), to deal in the Software without restriction, including |
|
| 9 | + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
| 10 | + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished |
|
| 11 | + * to do so, subject to the following conditions: |
|
| 12 | + * |
|
| 13 | + * The above copyright notice and this permission notice shall be included in all copies or |
|
| 14 | + * substantial portions of the Software. |
|
| 15 | + * |
|
| 16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
| 17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
|
| 18 | + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
| 19 | + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
|
| 20 | + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
| 21 | + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
| 22 | + * |
|
| 23 | + */ |
|
| 24 | + |
|
| 25 | +#ifndef _ES8311_H |
|
| 26 | +#define _ES8311_H |
|
| 27 | + |
|
| 28 | +#include "audio_hal.h" |
|
| 29 | +#include "esp_types.h" |
|
| 30 | +#include "esxxx_common.h" |
|
| 31 | + |
|
| 32 | +/* |
|
| 33 | + * ES8311_REGISTER NAME_REG_REGISTER ADDRESS |
|
| 34 | + */ |
|
| 35 | +#define ES8311_RESET_REG00 0x00 /*reset digital,csm,clock manager etc.*/ |
|
| 36 | + |
|
| 37 | +/* |
|
| 38 | + * Clock Scheme Register definition |
|
| 39 | + */ |
|
| 40 | +#define ES8311_CLK_MANAGER_REG01 0x01 /* select clk src for mclk, enable clock for codec */ |
|
| 41 | +#define ES8311_CLK_MANAGER_REG02 0x02 /* clk divider and clk multiplier */ |
|
| 42 | +#define ES8311_CLK_MANAGER_REG03 0x03 /* adc fsmode and osr */ |
|
| 43 | +#define ES8311_CLK_MANAGER_REG04 0x04 /* dac osr */ |
|
| 44 | +#define ES8311_CLK_MANAGER_REG05 0x05 /* clk divier for adc and dac */ |
|
| 45 | +#define ES8311_CLK_MANAGER_REG06 0x06 /* bclk inverter and divider */ |
|
| 46 | +#define ES8311_CLK_MANAGER_REG07 0x07 /* tri-state, lrck divider */ |
|
| 47 | +#define ES8311_CLK_MANAGER_REG08 0x08 /* lrck divider */ |
|
| 48 | +/* |
|
| 49 | + * SDP |
|
| 50 | + */ |
|
| 51 | +#define ES8311_SDPIN_REG09 0x09 /* dac serial digital port */ |
|
| 52 | +#define ES8311_SDPOUT_REG0A 0x0A /* adc serial digital port */ |
|
| 53 | +/* |
|
| 54 | + * SYSTEM |
|
| 55 | + */ |
|
| 56 | +#define ES8311_SYSTEM_REG0B 0x0B /* system */ |
|
| 57 | +#define ES8311_SYSTEM_REG0C 0x0C /* system */ |
|
| 58 | +#define ES8311_SYSTEM_REG0D 0x0D /* system, power up/down */ |
|
| 59 | +#define ES8311_SYSTEM_REG0E 0x0E /* system, power up/down */ |
|
| 60 | +#define ES8311_SYSTEM_REG0F 0x0F /* system, low power */ |
|
| 61 | +#define ES8311_SYSTEM_REG10 0x10 /* system */ |
|
| 62 | +#define ES8311_SYSTEM_REG11 0x11 /* system */ |
|
| 63 | +#define ES8311_SYSTEM_REG12 0x12 /* system, Enable DAC */ |
|
| 64 | +#define ES8311_SYSTEM_REG13 0x13 /* system */ |
|
| 65 | +#define ES8311_SYSTEM_REG14 0x14 /* system, select DMIC, select analog pga gain */ |
|
| 66 | +/* |
|
| 67 | + * ADC |
|
| 68 | + */ |
|
| 69 | +#define ES8311_ADC_REG15 0x15 /* ADC, adc ramp rate, dmic sense */ |
|
| 70 | +#define ES8311_ADC_REG16 0x16 /* ADC */ |
|
| 71 | +#define ES8311_ADC_REG17 0x17 /* ADC, volume */ |
|
| 72 | +#define ES8311_ADC_REG18 0x18 /* ADC, alc enable and winsize */ |
|
| 73 | +#define ES8311_ADC_REG19 0x19 /* ADC, alc maxlevel */ |
|
| 74 | +#define ES8311_ADC_REG1A 0x1A /* ADC, alc automute */ |
|
| 75 | +#define ES8311_ADC_REG1B 0x1B /* ADC, alc automute, adc hpf s1 */ |
|
| 76 | +#define ES8311_ADC_REG1C 0x1C /* ADC, equalizer, hpf s2 */ |
|
| 77 | +/* |
|
| 78 | + * DAC |
|
| 79 | + */ |
|
| 80 | +#define ES8311_DAC_REG31 0x31 /* DAC, mute */ |
|
| 81 | +#define ES8311_DAC_REG32 0x32 /* DAC, volume */ |
|
| 82 | +#define ES8311_DAC_REG33 0x33 /* DAC, offset */ |
|
| 83 | +#define ES8311_DAC_REG34 0x34 /* DAC, drc enable, drc winsize */ |
|
| 84 | +#define ES8311_DAC_REG35 0x35 /* DAC, drc maxlevel, minilevel */ |
|
| 85 | +#define ES8311_DAC_REG37 0x37 /* DAC, ramprate */ |
|
| 86 | +/* |
|
| 87 | + *GPIO |
|
| 88 | + */ |
|
| 89 | +#define ES8311_GPIO_REG44 0x44 /* GPIO, dac2adc for test */ |
|
| 90 | +#define ES8311_GP_REG45 0x45 /* GP CONTROL */ |
|
| 91 | +/* |
|
| 92 | + * CHIP |
|
| 93 | + */ |
|
| 94 | +#define ES8311_CHD1_REGFD 0xFD /* CHIP ID1 */ |
|
| 95 | +#define ES8311_CHD2_REGFE 0xFE /* CHIP ID2 */ |
|
| 96 | +#define ES8311_CHVER_REGFF 0xFF /* VERSION */ |
|
| 97 | +#define ES8311_CHD1_REGFD 0xFD /* CHIP ID1 */ |
|
| 98 | + |
|
| 99 | +#define ES8311_MAX_REGISTER 0xFF |
|
| 100 | + |
|
| 101 | +typedef enum { |
|
| 102 | + ES8311_MIC_GAIN_MIN = -1, |
|
| 103 | + ES8311_MIC_GAIN_0DB, |
|
| 104 | + ES8311_MIC_GAIN_6DB, |
|
| 105 | + ES8311_MIC_GAIN_12DB, |
|
| 106 | + ES8311_MIC_GAIN_18DB, |
|
| 107 | + ES8311_MIC_GAIN_24DB, |
|
| 108 | + ES8311_MIC_GAIN_30DB, |
|
| 109 | + ES8311_MIC_GAIN_36DB, |
|
| 110 | + ES8311_MIC_GAIN_42DB, |
|
| 111 | + ES8311_MIC_GAIN_MAX |
|
| 112 | +} es8311_mic_gain_t; |
|
| 113 | + |
|
| 114 | +/* |
|
| 115 | + * @brief Initialize ES8311 codec chip |
|
| 116 | + * |
|
| 117 | + * @param codec_cfg configuration of ES8311 |
|
| 118 | + * |
|
| 119 | + * @return |
|
| 120 | + * - ESP_OK |
|
| 121 | + * - ESP_FAIL |
|
| 122 | + */ |
|
| 123 | +esp_err_t es8311_codec_init(audio_hal_codec_config_t *codec_cfg); |
|
| 124 | + |
|
| 125 | +/** |
|
| 126 | + * @brief Deinitialize ES8311 codec chip |
|
| 127 | + * |
|
| 128 | + * @return |
|
| 129 | + * - ESP_OK |
|
| 130 | + * - ESP_FAIL |
|
| 131 | + */ |
|
| 132 | +esp_err_t es8311_codec_deinit(void); |
|
| 133 | + |
|
| 134 | +/** |
|
| 135 | + * @brief Control ES8311 codec chip |
|
| 136 | + * |
|
| 137 | + * @param mode codec mode |
|
| 138 | + * @param ctrl_state start or stop decode or encode progress |
|
| 139 | + * |
|
| 140 | + * @return |
|
| 141 | + * - ESP_FAIL Parameter error |
|
| 142 | + * - ESP_OK Success |
|
| 143 | + */ |
|
| 144 | +esp_err_t es8311_codec_ctrl_state(audio_hal_codec_mode_t mode, audio_hal_ctrl_t ctrl_state); |
|
| 145 | + |
|
| 146 | +/** |
|
| 147 | + * @brief Configure ES8311 codec mode and I2S interface |
|
| 148 | + * |
|
| 149 | + * @param mode codec mode |
|
| 150 | + * @param iface I2S config |
|
| 151 | + * |
|
| 152 | + * @return |
|
| 153 | + * - ESP_FAIL Parameter error |
|
| 154 | + * - ESP_OK Success |
|
| 155 | + */ |
|
| 156 | +esp_err_t es8311_codec_config_i2s(audio_hal_codec_mode_t mode, audio_hal_codec_i2s_iface_t *iface); |
|
| 157 | + |
|
| 158 | +/** |
|
| 159 | + * @brief Configure ES8311 DAC mute or not. Basically you can use this function to mute the output or unmute |
|
| 160 | + * |
|
| 161 | + * @param enable enable(1) or disable(0) |
|
| 162 | + * |
|
| 163 | + * @return |
|
| 164 | + * - ESP_FAIL Parameter error |
|
| 165 | + * - ESP_OK Success |
|
| 166 | + */ |
|
| 167 | +esp_err_t es8311_set_voice_mute(bool enable); |
|
| 168 | + |
|
| 169 | +/** |
|
| 170 | + * @brief Set voice volume |
|
| 171 | + * |
|
| 172 | + * @param volume: voice volume (0~100) |
|
| 173 | + * |
|
| 174 | + * @return |
|
| 175 | + * - ESP_OK |
|
| 176 | + * - ESP_FAIL |
|
| 177 | + */ |
|
| 178 | +esp_err_t es8311_codec_set_voice_volume(int volume); |
|
| 179 | + |
|
| 180 | +/** |
|
| 181 | + * @brief Get voice volume |
|
| 182 | + * |
|
| 183 | + * @param[out] *volume: voice volume (0~100) |
|
| 184 | + * |
|
| 185 | + * @return |
|
| 186 | + * - ESP_OK |
|
| 187 | + * - ESP_FAIL |
|
| 188 | + */ |
|
| 189 | +esp_err_t es8311_codec_get_voice_volume(int *volume); |
|
| 190 | + |
|
| 191 | +/** |
|
| 192 | + * @brief Configure ES8311 I2S format |
|
| 193 | + * |
|
| 194 | + * @param mod: set ADC or DAC or both |
|
| 195 | + * @param cfg: ES8388 I2S format |
|
| 196 | + * |
|
| 197 | + * @return |
|
| 198 | + * - ESP_OK |
|
| 199 | + * - ESP_FAIL |
|
| 200 | + */ |
|
| 201 | +esp_err_t es8311_config_fmt(es_i2s_fmt_t fmt); |
|
| 202 | + |
|
| 203 | +/** |
|
| 204 | + * @brief Configure ES8311 data sample bits |
|
| 205 | + * |
|
| 206 | + * @param mode: set ADC or DAC or both |
|
| 207 | + * @param bit_per_sample: bit number of per sample |
|
| 208 | + * |
|
| 209 | + * @return |
|
| 210 | + * - ESP_OK |
|
| 211 | + * - ESP_FAIL |
|
| 212 | + */ |
|
| 213 | +esp_err_t es8311_set_bits_per_sample(audio_hal_iface_bits_t bits); |
|
| 214 | + |
|
| 215 | +/** |
|
| 216 | + * @brief Start ES8311 codec chip |
|
| 217 | + * |
|
| 218 | + * @param mode: set ADC or DAC or both |
|
| 219 | + * |
|
| 220 | + * @return |
|
| 221 | + * - ESP_OK |
|
| 222 | + * - ESP_FAIL |
|
| 223 | + */ |
|
| 224 | +esp_err_t es8311_start(es_module_t mode); |
|
| 225 | + |
|
| 226 | +/** |
|
| 227 | + * @brief Stop ES8311 codec chip |
|
| 228 | + * |
|
| 229 | + * @param mode: set ADC or DAC or both |
|
| 230 | + * |
|
| 231 | + * @return |
|
| 232 | + * - ESP_OK |
|
| 233 | + * - ESP_FAIL |
|
| 234 | + */ |
|
| 235 | +esp_err_t es8311_stop(es_module_t mode); |
|
| 236 | + |
|
| 237 | +#endif |
Chip-cn-dat/everest-semi-dat/ES8311-dat/ES8311-SDK-dat/example/example_config.h
| ... | ... | @@ -0,0 +1,33 @@ |
| 1 | +/* |
|
| 2 | + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD |
|
| 3 | + * |
|
| 4 | + * SPDX-License-Identifier: CC0-1.0 |
|
| 5 | + */ |
|
| 6 | + |
|
| 7 | +#pragma once |
|
| 8 | + |
|
| 9 | +#include "sdkconfig.h" |
|
| 10 | + |
|
| 11 | +/* Example configurations */ |
|
| 12 | +#define EXAMPLE_RECV_BUF_SIZE (2400) |
|
| 13 | +#define EXAMPLE_SAMPLE_RATE (16000) |
|
| 14 | +#define EXAMPLE_MCLK_MULTIPLE (384) // If not using 24-bit data width, 256 should be enough |
|
| 15 | +#define EXAMPLE_MCLK_FREQ_HZ (EXAMPLE_SAMPLE_RATE * EXAMPLE_MCLK_MULTIPLE) |
|
| 16 | +#define EXAMPLE_VOICE_VOLUME CONFIG_EXAMPLE_VOICE_VOLUME |
|
| 17 | +#define EXAMPLE_PA_CTRL_IO CONFIG_EXAMPLE_PA_CTRL_IO |
|
| 18 | +#if CONFIG_EXAMPLE_MODE_ECHO |
|
| 19 | +#define EXAMPLE_MIC_GAIN CONFIG_EXAMPLE_MIC_GAIN |
|
| 20 | +#endif |
|
| 21 | + |
|
| 22 | +/* I2C port and GPIOs */ |
|
| 23 | +#define I2C_NUM (0) |
|
| 24 | +#define I2C_SCL_IO CONFIG_EXAMPLE_I2C_SCL_IO |
|
| 25 | +#define I2C_SDA_IO CONFIG_EXAMPLE_I2C_SDA_IO |
|
| 26 | + |
|
| 27 | +/* I2S port and GPIOs */ |
|
| 28 | +#define I2S_NUM (0) |
|
| 29 | +#define I2S_MCK_IO CONFIG_EXAMPLE_I2S_MCLK_IO |
|
| 30 | +#define I2S_BCK_IO CONFIG_EXAMPLE_I2S_BCLK_IO |
|
| 31 | +#define I2S_WS_IO CONFIG_EXAMPLE_I2S_WS_IO |
|
| 32 | +#define I2S_DO_IO CONFIG_EXAMPLE_I2S_DOUT_IO |
|
| 33 | +#define I2S_DI_IO CONFIG_EXAMPLE_I2S_DIN_IO |
Chip-cn-dat/everest-semi-dat/ES8311-dat/ES8311-SDK-dat/example/i2s_es8311_example.c
| ... | ... | @@ -0,0 +1,251 @@ |
| 1 | +/* |
|
| 2 | + * SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD |
|
| 3 | + * |
|
| 4 | + * SPDX-License-Identifier: CC0-1.0 |
|
| 5 | + */ |
|
| 6 | + |
|
| 7 | +#include <stdio.h> |
|
| 8 | +#include <string.h> |
|
| 9 | +#include "sdkconfig.h" |
|
| 10 | +#include "freertos/FreeRTOS.h" |
|
| 11 | +#include "freertos/task.h" |
|
| 12 | +#include "driver/i2s_std.h" |
|
| 13 | +#include "driver/i2c_master.h" |
|
| 14 | +#include "driver/gpio.h" |
|
| 15 | +#include "esp_system.h" |
|
| 16 | +#include "esp_codec_dev_defaults.h" |
|
| 17 | +#include "esp_codec_dev.h" |
|
| 18 | +#include "esp_codec_dev_vol.h" |
|
| 19 | +#include "esp_check.h" |
|
| 20 | +#include "example_config.h" |
|
| 21 | + |
|
| 22 | +static const char *TAG = "i2s_es8311"; |
|
| 23 | +static const char err_reason[][30] = {"input param is invalid", |
|
| 24 | + "operation timeout" |
|
| 25 | + }; |
|
| 26 | +static i2s_chan_handle_t tx_handle = NULL; |
|
| 27 | +static i2s_chan_handle_t rx_handle = NULL; |
|
| 28 | + |
|
| 29 | +/* Import music file as buffer */ |
|
| 30 | +#if CONFIG_EXAMPLE_MODE_MUSIC |
|
| 31 | +extern const uint8_t music_pcm_start[] asm("_binary_canon_pcm_start"); |
|
| 32 | +extern const uint8_t music_pcm_end[] asm("_binary_canon_pcm_end"); |
|
| 33 | +#endif |
|
| 34 | + |
|
| 35 | +static esp_err_t es8311_codec_init(void) |
|
| 36 | +{ |
|
| 37 | + /* Initialize I2C peripheral */ |
|
| 38 | + i2c_master_bus_handle_t i2c_bus_handle = NULL; |
|
| 39 | + i2c_master_bus_config_t i2c_mst_cfg = { |
|
| 40 | + .i2c_port = I2C_NUM, |
|
| 41 | + .sda_io_num = I2C_SDA_IO, |
|
| 42 | + .scl_io_num = I2C_SCL_IO, |
|
| 43 | + .clk_source = I2C_CLK_SRC_DEFAULT, |
|
| 44 | + .glitch_ignore_cnt = 7, |
|
| 45 | + /* Pull-up internally for no external pull-up case. |
|
| 46 | + Suggest to use external pull-up to ensure a strong enough pull-up. */ |
|
| 47 | + .flags.enable_internal_pullup = true, |
|
| 48 | + }; |
|
| 49 | + ESP_ERROR_CHECK(i2c_new_master_bus(&i2c_mst_cfg, &i2c_bus_handle)); |
|
| 50 | + |
|
| 51 | + /* Create control interface with I2C bus handle */ |
|
| 52 | + audio_codec_i2c_cfg_t i2c_cfg = { |
|
| 53 | + .port = I2C_NUM, |
|
| 54 | + .addr = ES8311_CODEC_DEFAULT_ADDR, |
|
| 55 | + .bus_handle = i2c_bus_handle, |
|
| 56 | + }; |
|
| 57 | + const audio_codec_ctrl_if_t *ctrl_if = audio_codec_new_i2c_ctrl(&i2c_cfg); |
|
| 58 | + assert(ctrl_if); |
|
| 59 | + |
|
| 60 | + /* Create data interface with I2S bus handle */ |
|
| 61 | + audio_codec_i2s_cfg_t i2s_cfg = { |
|
| 62 | + .port = I2S_NUM, |
|
| 63 | + .rx_handle = rx_handle, |
|
| 64 | + .tx_handle = tx_handle, |
|
| 65 | + }; |
|
| 66 | + const audio_codec_data_if_t *data_if = audio_codec_new_i2s_data(&i2s_cfg); |
|
| 67 | + assert(data_if); |
|
| 68 | + |
|
| 69 | + /* Create ES8311 interface handle */ |
|
| 70 | + const audio_codec_gpio_if_t *gpio_if = audio_codec_new_gpio(); |
|
| 71 | + assert(gpio_if); |
|
| 72 | + es8311_codec_cfg_t es8311_cfg = { |
|
| 73 | + .ctrl_if = ctrl_if, |
|
| 74 | + .gpio_if = gpio_if, |
|
| 75 | + .codec_mode = ESP_CODEC_DEV_WORK_MODE_BOTH, |
|
| 76 | + .master_mode = false, |
|
| 77 | + .use_mclk = I2S_MCK_IO >= 0, |
|
| 78 | + .pa_pin = EXAMPLE_PA_CTRL_IO, |
|
| 79 | + .pa_reverted = false, |
|
| 80 | + .hw_gain = { |
|
| 81 | + .pa_voltage = 5.0, |
|
| 82 | + .codec_dac_voltage = 3.3, |
|
| 83 | + }, |
|
| 84 | + .mclk_div = EXAMPLE_MCLK_MULTIPLE, |
|
| 85 | + }; |
|
| 86 | + const audio_codec_if_t *es8311_if = es8311_codec_new(&es8311_cfg); |
|
| 87 | + assert(es8311_if); |
|
| 88 | + |
|
| 89 | + /* Create the top codec handle with ES8311 interface handle and data interface */ |
|
| 90 | + esp_codec_dev_cfg_t dev_cfg = { |
|
| 91 | + .dev_type = ESP_CODEC_DEV_TYPE_IN_OUT, |
|
| 92 | + .codec_if = es8311_if, |
|
| 93 | + .data_if = data_if, |
|
| 94 | + }; |
|
| 95 | + esp_codec_dev_handle_t codec_handle = esp_codec_dev_new(&dev_cfg); |
|
| 96 | + assert(codec_handle); |
|
| 97 | + |
|
| 98 | + /* Specify the sample configurations and open the device */ |
|
| 99 | + esp_codec_dev_sample_info_t sample_cfg = { |
|
| 100 | + .bits_per_sample = I2S_DATA_BIT_WIDTH_16BIT, |
|
| 101 | + .channel = 2, |
|
| 102 | + .channel_mask = 0x03, |
|
| 103 | + .sample_rate = EXAMPLE_SAMPLE_RATE, |
|
| 104 | + .mclk_multiple = EXAMPLE_MCLK_MULTIPLE, |
|
| 105 | + }; |
|
| 106 | + if (esp_codec_dev_open(codec_handle, &sample_cfg) != ESP_CODEC_DEV_OK) { |
|
| 107 | + ESP_LOGE(TAG, "Open codec device failed"); |
|
| 108 | + return ESP_FAIL; |
|
| 109 | + } |
|
| 110 | + |
|
| 111 | + /* Set the initial volume and gain */ |
|
| 112 | + if (esp_codec_dev_set_out_vol(codec_handle, EXAMPLE_VOICE_VOLUME) != ESP_CODEC_DEV_OK) { |
|
| 113 | + ESP_LOGE(TAG, "set output volume failed"); |
|
| 114 | + return ESP_FAIL; |
|
| 115 | + } |
|
| 116 | +#if CONFIG_EXAMPLE_MODE_ECHO |
|
| 117 | + if (esp_codec_dev_set_in_gain(codec_handle, EXAMPLE_MIC_GAIN) != ESP_CODEC_DEV_OK) { |
|
| 118 | + ESP_LOGE(TAG, "set input gain failed"); |
|
| 119 | + return ESP_FAIL; |
|
| 120 | + } |
|
| 121 | +#endif |
|
| 122 | + return ESP_OK; |
|
| 123 | +} |
|
| 124 | + |
|
| 125 | +static esp_err_t i2s_driver_init(void) |
|
| 126 | +{ |
|
| 127 | + i2s_chan_config_t chan_cfg = I2S_CHANNEL_DEFAULT_CONFIG(I2S_NUM, I2S_ROLE_MASTER); |
|
| 128 | + chan_cfg.auto_clear = true; // Auto clear the legacy data in the DMA buffer |
|
| 129 | + ESP_ERROR_CHECK(i2s_new_channel(&chan_cfg, &tx_handle, &rx_handle)); |
|
| 130 | + i2s_std_config_t std_cfg = { |
|
| 131 | + .clk_cfg = I2S_STD_CLK_DEFAULT_CONFIG(EXAMPLE_SAMPLE_RATE), |
|
| 132 | + .slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO), |
|
| 133 | + .gpio_cfg = { |
|
| 134 | + .mclk = I2S_MCK_IO, |
|
| 135 | + .bclk = I2S_BCK_IO, |
|
| 136 | + .ws = I2S_WS_IO, |
|
| 137 | + .dout = I2S_DO_IO, |
|
| 138 | + .din = I2S_DI_IO, |
|
| 139 | + .invert_flags = { |
|
| 140 | + .mclk_inv = false, |
|
| 141 | + .bclk_inv = false, |
|
| 142 | + .ws_inv = false, |
|
| 143 | + }, |
|
| 144 | + }, |
|
| 145 | + }; |
|
| 146 | + |
|
| 147 | + ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_handle, &std_cfg)); |
|
| 148 | + ESP_ERROR_CHECK(i2s_channel_init_std_mode(rx_handle, &std_cfg)); |
|
| 149 | + ESP_ERROR_CHECK(i2s_channel_enable(tx_handle)); |
|
| 150 | + ESP_ERROR_CHECK(i2s_channel_enable(rx_handle)); |
|
| 151 | + return ESP_OK; |
|
| 152 | +} |
|
| 153 | + |
|
| 154 | +#if CONFIG_EXAMPLE_MODE_MUSIC |
|
| 155 | +static void i2s_music(void *args) |
|
| 156 | +{ |
|
| 157 | + esp_err_t ret = ESP_OK; |
|
| 158 | + size_t bytes_write = 0; |
|
| 159 | + uint8_t *data_ptr = (uint8_t *)music_pcm_start; |
|
| 160 | + |
|
| 161 | + /* (Optional) Disable TX channel and preload the data before enabling the TX channel, |
|
| 162 | + * so that the valid data can be transmitted immediately */ |
|
| 163 | + ESP_ERROR_CHECK(i2s_channel_disable(tx_handle)); |
|
| 164 | + ESP_ERROR_CHECK(i2s_channel_preload_data(tx_handle, data_ptr, music_pcm_end - data_ptr, &bytes_write)); |
|
| 165 | + data_ptr += bytes_write; // Move forward the data pointer |
|
| 166 | + |
|
| 167 | + /* Enable the TX channel */ |
|
| 168 | + ESP_ERROR_CHECK(i2s_channel_enable(tx_handle)); |
|
| 169 | + while (1) { |
|
| 170 | + /* Write music to earphone */ |
|
| 171 | + ret = i2s_channel_write(tx_handle, data_ptr, music_pcm_end - data_ptr, &bytes_write, portMAX_DELAY); |
|
| 172 | + if (ret != ESP_OK) { |
|
| 173 | + /* Since we set timeout to 'portMAX_DELAY' in 'i2s_channel_write' |
|
| 174 | + so you won't reach here unless you set other timeout value, |
|
| 175 | + if timeout detected, it means write operation failed. */ |
|
| 176 | + ESP_LOGE(TAG, "[music] i2s write failed, %s", err_reason[ret == ESP_ERR_TIMEOUT]); |
|
| 177 | + abort(); |
|
| 178 | + } |
|
| 179 | + if (bytes_write > 0) { |
|
| 180 | + ESP_LOGI(TAG, "[music] i2s music played, %d bytes are written.", bytes_write); |
|
| 181 | + } else { |
|
| 182 | + ESP_LOGE(TAG, "[music] i2s music play failed."); |
|
| 183 | + abort(); |
|
| 184 | + } |
|
| 185 | + data_ptr = (uint8_t *)music_pcm_start; |
|
| 186 | + vTaskDelay(1000 / portTICK_PERIOD_MS); |
|
| 187 | + } |
|
| 188 | + vTaskDelete(NULL); |
|
| 189 | +} |
|
| 190 | + |
|
| 191 | +#else |
|
| 192 | +static void i2s_echo(void *args) |
|
| 193 | +{ |
|
| 194 | + int *mic_data = malloc(EXAMPLE_RECV_BUF_SIZE); |
|
| 195 | + if (!mic_data) { |
|
| 196 | + ESP_LOGE(TAG, "[echo] No memory for read data buffer"); |
|
| 197 | + abort(); |
|
| 198 | + } |
|
| 199 | + esp_err_t ret = ESP_OK; |
|
| 200 | + size_t bytes_read = 0; |
|
| 201 | + size_t bytes_write = 0; |
|
| 202 | + ESP_LOGI(TAG, "[echo] Echo start"); |
|
| 203 | + |
|
| 204 | + while (1) { |
|
| 205 | + memset(mic_data, 0, EXAMPLE_RECV_BUF_SIZE); |
|
| 206 | + /* Read sample data from mic */ |
|
| 207 | + ret = i2s_channel_read(rx_handle, mic_data, EXAMPLE_RECV_BUF_SIZE, &bytes_read, 1000); |
|
| 208 | + if (ret != ESP_OK) { |
|
| 209 | + ESP_LOGE(TAG, "[echo] i2s read failed, %s", err_reason[ret == ESP_ERR_TIMEOUT]); |
|
| 210 | + abort(); |
|
| 211 | + } |
|
| 212 | + /* Write sample data to earphone */ |
|
| 213 | + ret = i2s_channel_write(tx_handle, mic_data, EXAMPLE_RECV_BUF_SIZE, &bytes_write, 1000); |
|
| 214 | + if (ret != ESP_OK) { |
|
| 215 | + ESP_LOGE(TAG, "[echo] i2s write failed, %s", err_reason[ret == ESP_ERR_TIMEOUT]); |
|
| 216 | + abort(); |
|
| 217 | + } |
|
| 218 | + if (bytes_read != bytes_write) { |
|
| 219 | + ESP_LOGW(TAG, "[echo] %d bytes read but only %d bytes are written", bytes_read, bytes_write); |
|
| 220 | + } |
|
| 221 | + } |
|
| 222 | + vTaskDelete(NULL); |
|
| 223 | +} |
|
| 224 | +#endif |
|
| 225 | + |
|
| 226 | +void app_main(void) |
|
| 227 | +{ |
|
| 228 | + printf("i2s es8311 codec example start\n-----------------------------\n"); |
|
| 229 | + /* Initialize i2s peripheral */ |
|
| 230 | + if (i2s_driver_init() != ESP_OK) { |
|
| 231 | + ESP_LOGE(TAG, "i2s driver init failed"); |
|
| 232 | + abort(); |
|
| 233 | + } else { |
|
| 234 | + ESP_LOGI(TAG, "i2s driver init success"); |
|
| 235 | + } |
|
| 236 | + /* Initialize i2c peripheral and config es8311 codec by i2c */ |
|
| 237 | + if (es8311_codec_init() != ESP_OK) { |
|
| 238 | + ESP_LOGE(TAG, "es8311 codec init failed"); |
|
| 239 | + abort(); |
|
| 240 | + } else { |
|
| 241 | + ESP_LOGI(TAG, "es8311 codec init success"); |
|
| 242 | + } |
|
| 243 | + |
|
| 244 | +#if CONFIG_EXAMPLE_MODE_MUSIC |
|
| 245 | + /* Play a piece of music in music mode */ |
|
| 246 | + xTaskCreate(i2s_music, "i2s_music", 4096, NULL, 5, NULL); |
|
| 247 | +#else |
|
| 248 | + /* Echo the sound from MIC in echo mode */ |
|
| 249 | + xTaskCreate(i2s_echo, "i2s_echo", 8192, NULL, 5, NULL); |
|
| 250 | +#endif |
|
| 251 | +} |
Chip-cn-dat/everest-semi-dat/ES8311-dat/ES8311-SDK-dat/test/ES8311-code-mic2/ES8311-code-mic2.ino
| ... | ... | @@ -1,78 +1,147 @@ |
| 1 | 1 | #include <Wire.h> |
| 2 | -#include <ESP_I2S.h> |
|
| 2 | +#include <driver/i2s.h> |
|
| 3 | 3 | |
| 4 | -// PIN CONFIGURATION |
|
| 4 | +// ========== PIN CONFIGURATION ========== |
|
| 5 | 5 | #define I2C_SDA 5 |
| 6 | 6 | #define I2C_SCL 4 |
| 7 | 7 | |
| 8 | 8 | #define I2S_BCLK 14 |
| 9 | -#define I2S_LRCK 12 |
|
| 10 | -#define I2S_DOUT 13 |
|
| 11 | -#define I2S_DIN 11 // unused (DAC playback only) |
|
| 12 | -#define I2S_MCLK 6 |
|
| 9 | +#define I2S_LRCK 13 |
|
| 10 | +#define I2S_DOUT 12 // unused (reading from mic) |
|
| 11 | +#define I2S_DIN 15 // ES8311 SDTO (data out) |
|
| 12 | +#define I2S_MCLK 16 |
|
| 13 | 13 | |
| 14 | -#define ES8311_ADDR 0x18 |
|
| 14 | +#define ES8311_ADDR 0x18 |
|
| 15 | +#define SAMPLE_RATE 16000 |
|
| 15 | 16 | |
| 16 | -I2SClass i2s; |
|
| 17 | +// ========== I2C HELPERS ========== |
|
| 18 | +bool writeReg(uint8_t reg, uint8_t val) { |
|
| 19 | + Wire.beginTransmission(ES8311_ADDR); |
|
| 20 | + Wire.write(reg); |
|
| 21 | + Wire.write(val); |
|
| 22 | + return Wire.endTransmission() == 0; |
|
| 23 | +} |
|
| 17 | 24 | |
| 18 | -void writeReg(uint8_t reg, uint8_t value) { |
|
| 25 | +uint8_t readReg(uint8_t reg) { |
|
| 19 | 26 | Wire.beginTransmission(ES8311_ADDR); |
| 20 | 27 | Wire.write(reg); |
| 21 | - Wire.write(value); |
|
| 22 | - Wire.endTransmission(); |
|
| 28 | + Wire.endTransmission(false); |
|
| 29 | + Wire.requestFrom(ES8311_ADDR, (uint8_t)1); |
|
| 30 | + return Wire.available() ? Wire.read() : 0xFF; |
|
| 31 | +} |
|
| 32 | + |
|
| 33 | +void dumpRegs() { |
|
| 34 | + Serial.println("--- ES8311 Registers ---"); |
|
| 35 | + uint8_t regs[] = {0x00,0x01,0x02,0x03,0x0A,0x0B,0x0D,0x0E, |
|
| 36 | + 0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x45}; |
|
| 37 | + for (int i = 0; i < (int)(sizeof(regs)/sizeof(regs[0])); i++) { |
|
| 38 | + Serial.printf(" REG[0x%02X] = 0x%02X\n", regs[i], readReg(regs[i])); |
|
| 39 | + } |
|
| 23 | 40 | } |
| 24 | 41 | |
| 25 | -void init_ES8311() { |
|
| 42 | +// ========== ES8311 INIT ========== |
|
| 43 | +bool init_ES8311() { |
|
| 26 | 44 | // 1. Reset |
| 27 | - writeReg(0x00, 0x80); delay(50); |
|
| 28 | - writeReg(0x00, 0x00); |
|
| 29 | - |
|
| 30 | - // 2. Clock Management (Slave Mode) |
|
| 31 | - writeReg(0x01, 0x30); // Enable MCLK and Clocks |
|
| 32 | - writeReg(0x02, 0x10); // ADC Clock |
|
| 33 | - writeReg(0x03, 0x10); // DAC Clock |
|
| 34 | - |
|
| 35 | - // 3. I2S Format (Phillips 16-bit) |
|
| 36 | - writeReg(0x0A, 0x00); // Phillips Mode |
|
| 37 | - writeReg(0x0B, 0x0C); // 16-bit word length (0x0C) |
|
| 38 | - |
|
| 39 | - // 4. Power & Analog Path |
|
| 40 | - writeReg(0x0D, 0x03); // Power up Analog core |
|
| 41 | - writeReg(0x0E, 0x02); // Enable ADC Analog |
|
| 42 | - writeReg(0x13, 0x40); // SELECT MIC1 (MIC_P), Power up MICBIAS |
|
| 43 | - writeReg(0x14, 0x1A); // PGA Gain +24dB |
|
| 44 | - writeReg(0x15, 0x00); // SELECT ANALOG ADC (0x40 was Digital Mic mode) |
|
| 45 | - writeReg(0x16, 0x00); // ALC Off |
|
| 46 | - writeReg(0x17, 0x00); // Volume Max |
|
| 47 | - |
|
| 48 | - // 5. Digital Enable |
|
| 49 | - writeReg(0x45, 0x01); |
|
| 50 | - Serial.println("ES8311 Configured (Phillips, MIC1, +24dB)"); |
|
| 45 | + if (!writeReg(0x00, 0x1F)) { Serial.println("I2C FAIL - check wiring"); return false; } |
|
| 46 | + delay(10); |
|
| 47 | + writeReg(0x00, 0x00); delay(10); |
|
| 48 | + |
|
| 49 | + // 2. Clock: MCLK divider — MCLK=4.096MHz (256 × 16kHz) |
|
| 50 | + writeReg(0x01, 0x30); // MCLK input enabled, clock divider on |
|
| 51 | + writeReg(0x02, 0x10); // ADC: fs = MCLK/256 |
|
| 52 | + writeReg(0x03, 0x10); // DAC: fs = MCLK/256 |
|
| 53 | + |
|
| 54 | + // 3. I2S format: Philips, 16-bit |
|
| 55 | + writeReg(0x0A, 0x00); // I2S Philips mode |
|
| 56 | + writeReg(0x0B, 0x0C); // bits[4:2]=011 → 16-bit |
|
| 57 | + |
|
| 58 | + // 4. Power up |
|
| 59 | + writeReg(0x0D, 0x01); delay(5); // digital core |
|
| 60 | + writeReg(0x0D, 0x03); delay(5); // analog + digital |
|
| 61 | + |
|
| 62 | + // 5. Analog path: MIC1 |
|
| 63 | + writeReg(0x0E, 0x06); // ADC + I/O buffer powered |
|
| 64 | + writeReg(0x13, 0x40); // MIC1 selected, MICBIAS on |
|
| 65 | + writeReg(0x14, 0x1A); // PGA gain +24 dB |
|
| 66 | + writeReg(0x15, 0x00); // ADC input = analog PGA |
|
| 67 | + writeReg(0x1A, 0x00); // MIC1 volume |
|
| 68 | + writeReg(0x1B, 0x00); // MIC2 volume |
|
| 69 | + |
|
| 70 | + // 6. ALC off, volume max |
|
| 71 | + writeReg(0x16, 0x00); // ALC disable |
|
| 72 | + writeReg(0x17, 0x00); // ADC volume |
|
| 73 | + writeReg(0x18, 0x00); // DAC volume L |
|
| 74 | + writeReg(0x19, 0x00); // DAC volume R |
|
| 75 | + |
|
| 76 | + // 7. Digital enable |
|
| 77 | + writeReg(0x45, 0x01); delay(10); |
|
| 78 | + |
|
| 79 | + Serial.println("ES8311 configured"); |
|
| 80 | + dumpRegs(); |
|
| 81 | + return true; |
|
| 82 | +} |
|
| 83 | + |
|
| 84 | +// ========== I2S SETUP (IDF driver — reliable) ========== |
|
| 85 | +void setupI2S() { |
|
| 86 | + i2s_config_t cfg = { |
|
| 87 | + .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX), |
|
| 88 | + .sample_rate = SAMPLE_RATE, |
|
| 89 | + .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, |
|
| 90 | + .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, |
|
| 91 | + .communication_format = I2S_COMM_FORMAT_STAND_I2S, |
|
| 92 | + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, |
|
| 93 | + .dma_buf_count = 4, |
|
| 94 | + .dma_buf_len = 128, |
|
| 95 | + .use_apll = true, |
|
| 96 | + .tx_desc_auto_clear = false, |
|
| 97 | + .fixed_mclk = SAMPLE_RATE * 256, |
|
| 98 | + }; |
|
| 99 | + |
|
| 100 | + i2s_pin_config_t pins = { |
|
| 101 | + .bck_io_num = I2S_BCLK, |
|
| 102 | + .ws_io_num = I2S_LRCK, |
|
| 103 | + .data_out_num = I2S_PIN_NO_CHANGE, |
|
| 104 | + .data_in_num = I2S_DIN, |
|
| 105 | + }; |
|
| 106 | + |
|
| 107 | + ESP_ERROR_CHECK(i2s_driver_install(I2S_NUM_0, &cfg, 0, NULL)); |
|
| 108 | + ESP_ERROR_CHECK(i2s_set_pin(I2S_NUM_0, &pins)); |
|
| 109 | + i2s_zero_dma_buffer(I2S_NUM_0); |
|
| 110 | + Serial.println("I2S RX ready"); |
|
| 51 | 111 | } |
| 52 | 112 | |
| 113 | +// ========== SETUP ========== |
|
| 53 | 114 | void setup() { |
| 54 | 115 | Serial.begin(115200); |
| 55 | - delay(1000); |
|
| 116 | + delay(2000); |
|
| 117 | + Serial.println("\n=== ES8311 Mic Test ==="); |
|
| 118 | + |
|
| 56 | 119 | Wire.begin(I2C_SDA, I2C_SCL); |
| 57 | - init_ES8311(); |
|
| 58 | - |
|
| 59 | - // STABLE I2S CONFIG |
|
| 60 | - i2s.setPins(I2S_BCLK, I2S_LRCK, I2S_DOUT, I2S_DIN, I2S_MCLK); |
|
| 61 | - |
|
| 62 | - // Use Phillips mode and 16-bit. Read both slots. |
|
| 63 | - if (!i2s.begin(I2S_MODE_STD, 16000, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO, I2S_STD_SLOT_BOTH)) { |
|
| 64 | - Serial.println("I2S Init Failed"); |
|
| 65 | - while (1); |
|
| 120 | + |
|
| 121 | + // I2C bus scan |
|
| 122 | + Serial.println("Scanning I2C bus..."); |
|
| 123 | + int found = 0; |
|
| 124 | + for (uint8_t addr = 1; addr < 127; addr++) { |
|
| 125 | + Wire.beginTransmission(addr); |
|
| 126 | + if (Wire.endTransmission() == 0) { |
|
| 127 | + Serial.printf(" Found 0x%02X\n", addr); |
|
| 128 | + found++; |
|
| 129 | + } |
|
| 66 | 130 | } |
| 67 | - Serial.println("I2S Ready (Stereo 16-bit)."); |
|
| 131 | + if (found == 0) { Serial.println("NO I2C devices found!"); while (1); } |
|
| 132 | + |
|
| 133 | + if (!init_ES8311()) { Serial.println("ES8311 init FAILED"); while (1); } |
|
| 134 | + setupI2S(); |
|
| 135 | + Serial.println("=== Ready — tap the mic! ===\n"); |
|
| 68 | 136 | } |
| 69 | 137 | |
| 138 | +// ========== LOOP ========== |
|
| 70 | 139 | void loop() { |
| 71 | - int16_t samples[2]; // [0] = Left, [1] = Right |
|
| 72 | - size_t bytes_read = i2s.readBytes((char*)samples, sizeof(samples)); |
|
| 73 | - |
|
| 74 | - if (bytes_read == sizeof(samples)) { |
|
| 75 | - // If you talk into the mic, these numbers should JUMP wildly |
|
| 76 | - Serial.printf("L:%6d R:%6d\n", samples[0], samples[1]); |
|
| 140 | + int16_t sample; |
|
| 141 | + size_t bytes_read = 0; |
|
| 142 | + |
|
| 143 | + esp_err_t err = i2s_read(I2S_NUM_0, &sample, sizeof(sample), &bytes_read, portMAX_DELAY); |
|
| 144 | + if (err == ESP_OK && bytes_read == sizeof(sample)) { |
|
| 145 | + Serial.println(sample); |
|
| 77 | 146 | } |
| 78 | 147 | } |
| ... | ... | \ No newline at end of file |
Chip-cn-dat/everest-semi-dat/ES8311-dat/ES8311-SDK-dat/test/ES8311-code-spk3-melody/ES8311-code-spk3-melody.ino
| ... | ... | @@ -1,35 +1,44 @@ |
| 1 | +/* |
|
| 2 | + * ES8311 Melody Player for ESP32-S3 + ES8311-NS4150B |
|
| 3 | + * |
|
| 4 | + * ES8311 init adapted from the official ESP-IDF es8311.c driver. |
|
| 5 | + * |
|
| 6 | + * Board wiring (from ES8311-dat): |
|
| 7 | + * GPIO 4 → SCL GPIO 5 → SDA |
|
| 8 | + * GPIO 6 → MCLK GPIO 11 → DIN (ESP32 DOUT → ES8311 SDIN) |
|
| 9 | + * GPIO 12 → LRCK GPIO 13 → DOUT (not used for playback) |
|
| 10 | + * GPIO 14 → SCLK (BCLK) |
|
| 11 | + */ |
|
| 12 | + |
|
| 1 | 13 | #include <Wire.h> |
| 2 | -#include <ESP_I2S.h> // Uses the standard ESP32 Arduino I2S library |
|
| 14 | +#include <driver/i2s.h> |
|
| 3 | 15 | |
| 4 | -// Fallback in case Arduino core doesn't define PI |
|
| 5 | 16 | #ifndef PI |
| 6 | 17 | #define PI 3.141592653589793f |
| 7 | 18 | #endif |
| 8 | 19 | |
| 9 | -// Define your board's pin layout (Change these values to match your specific board schematic) |
|
| 10 | -#define I2S_BCLK 14 |
|
| 11 | -#define I2S_LRCK 12 |
|
| 12 | -#define I2S_DOUT 13 |
|
| 13 | -#define I2S_DIN -1 // not used (DAC playback only) |
|
| 14 | - |
|
| 15 | -#define I2S_MCLK 6 |
|
| 16 | - |
|
| 17 | -#define I2C_SDA 5 |
|
| 18 | -#define I2C_SCL 4 |
|
| 20 | +// ==================== PIN MAPPING ==================== |
|
| 21 | +#define I2C_SDA 5 |
|
| 22 | +#define I2C_SCL 4 |
|
| 19 | 23 | |
| 24 | +#define I2S_MCLK 6 |
|
| 25 | +#define I2S_BCLK 14 |
|
| 26 | +#define I2S_LRCK 12 |
|
| 27 | +#define I2S_DOUT 11 // ESP32 DOUT → ES8311 SDIN |
|
| 28 | +#define I2S_DIN 13 // unused for playback |
|
| 20 | 29 | |
| 21 | -// NS4150 CTRL pin: hardware-pulled HIGH (no GPIO needed) |
|
| 30 | +#define PA_CTRL -1 |
|
| 22 | 31 | |
| 23 | -#define ES8311_ADDR 0x18 // Default I2C Address for ES8311 |
|
| 32 | +#define ES8311_ADDR 0x18 |
|
| 33 | +#define SAMPLE_RATE 16000 |
|
| 34 | +#define MCLK_HZ (SAMPLE_RATE * 256) // 4.096 MHz |
|
| 24 | 35 | |
| 25 | -I2SClass i2s; |
|
| 26 | - |
|
| 27 | -// Helper to write to ES8311 registers over I2C |
|
| 28 | -void writeReg(uint8_t reg, uint8_t value) { |
|
| 36 | +// ==================== I2C Helpers ==================== |
|
| 37 | +bool writeReg(uint8_t reg, uint8_t val) { |
|
| 29 | 38 | Wire.beginTransmission(ES8311_ADDR); |
| 30 | 39 | Wire.write(reg); |
| 31 | - Wire.write(value); |
|
| 32 | - Wire.endTransmission(); |
|
| 40 | + Wire.write(val); |
|
| 41 | + return Wire.endTransmission() == 0; |
|
| 33 | 42 | } |
| 34 | 43 | |
| 35 | 44 | uint8_t readReg(uint8_t reg) { |
| ... | ... | @@ -37,152 +46,164 @@ uint8_t readReg(uint8_t reg) { |
| 37 | 46 | Wire.write(reg); |
| 38 | 47 | Wire.endTransmission(false); |
| 39 | 48 | Wire.requestFrom((uint16_t)ES8311_ADDR, (uint8_t)1); |
| 40 | - if (Wire.available()) return Wire.read(); |
|
| 41 | - return 0; |
|
| 49 | + return Wire.available() ? Wire.read() : 0xFF; |
|
| 42 | 50 | } |
| 43 | 51 | |
| 44 | -void init_ES8311() { |
|
| 45 | - // === ES8311 Register Map (from arduino-audio-driver ES8311.h) === |
|
| 46 | - // 0x00=RESET, 0x01=CLK_MGR1, 0x02=CLK_MGR2, 0x03=CLK_MGR3(ADC OSR), |
|
| 47 | - // 0x04=CLK_MGR4(DAC OSR), 0x05=CLK_MGR5(ADC/DAC div), |
|
| 48 | - // 0x06=CLK_MGR6(BCLK div), 0x07=CLK_MGR7(LRCK H), 0x08=CLK_MGR8(LRCK L), |
|
| 49 | - // 0x09=SDP_IN(DAC I2S), 0x0A=SDP_OUT(ADC I2S), |
|
| 50 | - // 0x0B-0x0C=SYSTEM, 0x0D=ANALOG_PWR, 0x0E=SYSTEM, |
|
| 51 | - // 0x10-0x11=SYSTEM, 0x12-0x13=SYSTEM, |
|
| 52 | - // 0x14=SYSTEM(PGA/analog), 0x15-0x1C=ADC, |
|
| 53 | - // 0x31-0x35=DAC, 0x37=DAC_CTRL, 0x32=DAC_VOL, |
|
| 54 | - // 0xFD=CHIP_ID1, 0xFE=CHIP_ID2 |
|
| 55 | - |
|
| 56 | - // === 1. Initial register setup (before reset) === |
|
| 57 | - writeReg(0x01, 0x30); // CLK_MGR1: enable main clocks |
|
| 58 | - writeReg(0x02, 0x00); // CLK_MGR2: clear pre-divider |
|
| 59 | - writeReg(0x03, 0x10); // CLK_MGR3: ADC OSR=16x (default) |
|
| 60 | - writeReg(0x16, 0x24); // ADC_REG16: MIC gain initial |
|
| 61 | - writeReg(0x04, 0x10); // CLK_MGR4: DAC OSR=16x |
|
| 62 | - writeReg(0x05, 0x00); // CLK_MGR5: clear ADC/DAC dividers |
|
| 63 | - writeReg(0x0B, 0x00); // SYSTEM_REG0B |
|
| 64 | - writeReg(0x0C, 0x00); // SYSTEM_REG0C |
|
| 65 | - writeReg(0x10, 0x1F); // SYSTEM_REG10 |
|
| 66 | - writeReg(0x11, 0x7F); // SYSTEM_REG11 |
|
| 67 | - |
|
| 68 | - // === 2. Reset chip === |
|
| 69 | - writeReg(0x00, 0x80); // RESET: trigger reset |
|
| 70 | - delay(20); |
|
| 71 | - |
|
| 72 | - // === 3. Set Slave Mode (ESP32 is I2S Master) === |
|
| 73 | - uint8_t regv = readReg(0x00); |
|
| 74 | - regv &= 0xBF; // Clear bit 6 → Slave mode |
|
| 75 | - writeReg(0x00, regv); |
|
| 76 | - |
|
| 77 | - // === 4. Enable all internal clocks, use BCLK as clock source === |
|
| 78 | - // Using BCLK (SCLK) instead of MCLK pin avoids MCLK frequency mismatch |
|
| 79 | - writeReg(0x01, 0x3F); // CLK_MGR1: all clocks ON |
|
| 80 | - regv = readReg(0x01); |
|
| 81 | - regv |= 0x80; // Set bit 7 → clock source = BCLK (SCLK pin) |
|
| 82 | - writeReg(0x01, regv); |
|
| 83 | - |
|
| 84 | - // === 5. Clock dividers for 16kHz @ 4.096MHz MCLK (256*Fs) === |
|
| 85 | - // From coefficient table: {4096000, 16000, pre=1, mult=1, adc=1, dac=1, |
|
| 86 | - // fs=0, lrch=0, lrcl=0xFF, bck=4, osr=0x10} |
|
| 87 | - writeReg(0x02, 0x00); // CLK_MGR2: pre_div=1, multi=1 |
|
| 88 | - writeReg(0x03, 0x10); // CLK_MGR3: fs_mode=0, adc_osr=0x10 |
|
| 89 | - writeReg(0x04, 0x10); // CLK_MGR4: dac_osr=0x10 |
|
| 90 | - writeReg(0x05, 0x00); // CLK_MGR5: adc_div=1, dac_div=1 |
|
| 91 | - writeReg(0x06, 0x03); // CLK_MGR6: bclk_div=4 |
|
| 92 | - writeReg(0x07, 0x00); // CLK_MGR7: lrck_h=0 |
|
| 93 | - writeReg(0x08, 0xFF); // CLK_MGR8: lrck_l=0xFF |
|
| 94 | - |
|
| 95 | - // === 6. I2S Format: 16-bit Phillips (standard I2S) === |
|
| 96 | - writeReg(0x09, 0x0C); // SDP_IN: 16-bit I2S for DAC |
|
| 97 | - writeReg(0x0A, 0x0C); // SDP_OUT: 16-bit I2S for ADC |
|
| 98 | - |
|
| 99 | - // === 7. System init (from official driver) === |
|
| 100 | - writeReg(0x13, 0x10); // SYSTEM_REG13 |
|
| 101 | - writeReg(0x1B, 0x0A); // ADC_REG1B |
|
| 102 | - writeReg(0x1C, 0x6A); // ADC_REG1C |
|
| 103 | - |
|
| 104 | - Serial.println("ES8311 Init done (clock + I2S format)."); |
|
| 105 | - |
|
| 106 | - // === Verify chip ID === |
|
| 107 | - uint8_t chip_id1 = readReg(0xFD); |
|
| 108 | - uint8_t chip_id2 = readReg(0xFE); |
|
| 109 | - Serial.printf("ES8311 Chip ID: 0x%02X%02X (expect 0x8311)\n", chip_id1, chip_id2); |
|
| 52 | +void dumpRegs() { |
|
| 53 | + Serial.println("--- ES8311 Registers ---"); |
|
| 54 | + uint8_t regs[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, |
|
| 55 | + 0x09,0x0A,0x0D,0x0E,0x12,0x14,0x15,0x31,0x32,0x37,0x44,0x45}; |
|
| 56 | + for (int i = 0; i < (int)(sizeof(regs)/sizeof(regs[0])); i++) { |
|
| 57 | + Serial.printf(" REG[0x%02X] = 0x%02X\n", regs[i], readReg(regs[i])); |
|
| 58 | + } |
|
| 110 | 59 | } |
| 111 | 60 | |
| 112 | -void start_ES8311_DAC() { |
|
| 113 | - // === START sequence for DAC playback (from official driver) === |
|
| 114 | - // Powers up DAC, unmutes, routes audio to output |
|
| 115 | - |
|
| 116 | - // 1. Set PGA / analog control (max analog gain) |
|
| 117 | - writeReg(0x14, 0x3B); // SYSTEM_REG14: max PGA gain, no mic bias |
|
| 118 | - |
|
| 119 | - // 2. Unmute DAC on I2S interface (clear bit 6 in SDP_IN) |
|
| 120 | - uint8_t dac_iface = readReg(0x09) & 0xBF; |
|
| 121 | - writeReg(0x09, dac_iface); |
|
| 122 | - |
|
| 123 | - // 3. Unmute ADC on I2S interface (not needed, but harmless) |
|
| 124 | - uint8_t adc_iface = readReg(0x0A) & 0xBF; |
|
| 125 | - writeReg(0x0A, adc_iface); |
|
| 126 | - |
|
| 127 | - // 4. ADC digital volume = max |
|
| 128 | - writeReg(0x17, 0xBF); // ADC_REG17 |
|
| 129 | - |
|
| 130 | - // 5. System analog enable |
|
| 131 | - writeReg(0x0E, 0x02); // SYSTEM_REG0E |
|
| 132 | - |
|
| 133 | - // 6. System control |
|
| 134 | - writeReg(0x12, 0x00); // SYSTEM_REG12 |
|
| 135 | - |
|
| 136 | - // 7. Power up analog (DAC + ADC + full analog blocks) |
|
| 137 | - writeReg(0x0D, 0x03); // SYSTEM_REG0D: power up DAC + ADC analog |
|
| 138 | - |
|
| 139 | - // 8. ADC control |
|
| 140 | - writeReg(0x15, 0x40); // ADC_REG15 |
|
| 141 | - |
|
| 142 | - // 9. DAC control - max output drive |
|
| 143 | - writeReg(0x37, 0x78); // DAC_REG37: max DAC output drive (was 0x68) |
|
| 144 | - |
|
| 145 | - // 10. GPIO / digital |
|
| 146 | - writeReg(0x45, 0x00); // GP_REG45 |
|
| 147 | - |
|
| 148 | - // 11. DAC digital volume (0x00=mute, 0xBF=0dB, 0xFF=+6dB max) |
|
| 149 | - writeReg(0x32, 0xFF); // DAC_REG32: MAXIMUM volume |
|
| 61 | +// ==================== ES8311 Init (from es8311.c official driver) ==================== |
|
| 62 | +/* |
|
| 63 | + * Coefficient for 16kHz @ MCLK=4.096MHz (256 × 16kHz): |
|
| 64 | + * pre_div=1, pre_multi=1, adc_div=1, dac_div=1, |
|
| 65 | + * fs_mode=0, lrck_h=0, lrck_l=0xFF, bclk_div=4, adc_osr=16, dac_osr=16 |
|
| 66 | + */ |
|
| 67 | +bool init_ES8311_DAC() { |
|
| 68 | + // === 1. Pre-reset writes (es8311_codec_init) === |
|
| 69 | + writeReg(0x01, 0x30); |
|
| 70 | + writeReg(0x02, 0x00); |
|
| 71 | + writeReg(0x03, 0x10); |
|
| 72 | + writeReg(0x16, 0x24); |
|
| 73 | + writeReg(0x04, 0x10); |
|
| 74 | + writeReg(0x05, 0x00); |
|
| 75 | + writeReg(0x0B, 0x00); |
|
| 76 | + writeReg(0x0C, 0x00); |
|
| 77 | + writeReg(0x10, 0x1F); |
|
| 78 | + writeReg(0x11, 0x7F); |
|
| 79 | + |
|
| 80 | + // === 2. Reset === |
|
| 81 | + if (!writeReg(0x00, 0x80)) { Serial.println("I2C FAIL"); return false; } |
|
| 82 | + delay(20); |
|
| 83 | + writeReg(0x00, 0x00); |
|
| 84 | + |
|
| 85 | + // === 3. Slave mode (clear bit6) === |
|
| 86 | + uint8_t r = readReg(0x00); |
|
| 87 | + r &= 0xBF; |
|
| 88 | + writeReg(0x00, r); |
|
| 89 | + |
|
| 90 | + // === 4. Enable all clocks === |
|
| 91 | + writeReg(0x01, 0x3F); |
|
| 92 | + |
|
| 93 | + // === 5. Select MCLK pin as clock source (clear bit7) === |
|
| 94 | + r = readReg(0x01); |
|
| 95 | + r &= 0x7F; |
|
| 96 | + writeReg(0x01, r); |
|
| 97 | + |
|
| 98 | + // === 6. Clock dividers from coefficient table === |
|
| 99 | + // pre_div=1, pre_multi=1 → reg02 = 0x00 |
|
| 100 | + writeReg(0x02, 0x00); |
|
| 101 | + // fs_mode=0, adc_osr=16 → reg03 = 0x10 |
|
| 102 | + writeReg(0x03, 0x10); |
|
| 103 | + // dac_osr=16 → reg04 = 0x10 |
|
| 104 | + writeReg(0x04, 0x10); |
|
| 105 | + // adc_div=1, dac_div=1 → reg05 = 0x00 |
|
| 106 | + writeReg(0x05, 0x00); |
|
| 107 | + // bclk_div=4 → reg06 = 0x03 |
|
| 108 | + writeReg(0x06, 0x03); |
|
| 109 | + // lrck_h=0 → reg07 = 0x00 |
|
| 110 | + writeReg(0x07, 0x00); |
|
| 111 | + // lrck_l=0xFF → reg08 = 0xFF |
|
| 112 | + writeReg(0x08, 0xFF); |
|
| 113 | + |
|
| 114 | + // === 7. I2S format: Philips 16-bit === |
|
| 115 | + writeReg(0x09, 0x0C); |
|
| 116 | + writeReg(0x0A, 0x0C); |
|
| 117 | + |
|
| 118 | + // === 8. System init (from official driver) === |
|
| 119 | + writeReg(0x13, 0x10); |
|
| 120 | + writeReg(0x1B, 0x0A); |
|
| 121 | + writeReg(0x1C, 0x6A); |
|
| 122 | + writeReg(0x44, 0x08); |
|
| 123 | + |
|
| 124 | + // === 9. DAC start sequence (es8311_start in DAC mode) === |
|
| 125 | + // Unmute DAC (clear bit6 in reg09) |
|
| 126 | + r = readReg(0x09) & 0xBF; |
|
| 127 | + writeReg(0x09, r); |
|
| 128 | + // Unmute ADC (clear bit6 in reg0A) — harmless |
|
| 129 | + r = readReg(0x0A) & 0xBF; |
|
| 130 | + writeReg(0x0A, r); |
|
| 131 | + |
|
| 132 | + writeReg(0x32, 0xBF); // DAC volume = 0dB (official driver value) |
|
| 133 | + writeReg(0x17, 0xBF); // ADC volume |
|
| 134 | + writeReg(0x0E, 0x02); // Analog enable |
|
| 135 | + writeReg(0x12, 0x00); // System |
|
| 136 | + writeReg(0x14, 0x1A); // PGA + DMIC select (0=analog mic) |
|
| 137 | + writeReg(0x0D, 0x01); // Power digital only |
|
| 138 | + delay(5); |
|
| 139 | + writeReg(0x15, 0x40); // ADC control |
|
| 140 | + writeReg(0x37, 0x48); // DAC output drive |
|
| 141 | + writeReg(0x45, 0x00); // GPIO |
|
| 142 | + |
|
| 143 | + Serial.println("ES8311 DAC configured (es8311.c reference)"); |
|
| 144 | + dumpRegs(); |
|
| 145 | + return true; |
|
| 146 | +} |
|
| 150 | 147 | |
| 151 | - Serial.println("ES8311 DAC STARTED (powered, unmuted, routed)."); |
|
| 148 | +// ==================== I2S Setup ==================== |
|
| 149 | +void setupI2S() { |
|
| 150 | + i2s_config_t cfg = { |
|
| 151 | + .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), |
|
| 152 | + .sample_rate = SAMPLE_RATE, |
|
| 153 | + .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, |
|
| 154 | + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, |
|
| 155 | + .communication_format = I2S_COMM_FORMAT_STAND_I2S, |
|
| 156 | + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, |
|
| 157 | + .dma_buf_count = 4, |
|
| 158 | + .dma_buf_len = 256, |
|
| 159 | + .use_apll = true, |
|
| 160 | + .tx_desc_auto_clear = true, |
|
| 161 | + .fixed_mclk = MCLK_HZ, // 4.096 MHz for ES8311 MCLK pin |
|
| 162 | + }; |
|
| 163 | + |
|
| 164 | + i2s_pin_config_t pins = { |
|
| 165 | + .bck_io_num = I2S_BCLK, |
|
| 166 | + .ws_io_num = I2S_LRCK, |
|
| 167 | + .data_out_num = I2S_DOUT, |
|
| 168 | + .data_in_num = I2S_PIN_NO_CHANGE, |
|
| 169 | + }; |
|
| 170 | + |
|
| 171 | + ESP_ERROR_CHECK(i2s_driver_install(I2S_NUM_0, &cfg, 0, NULL)); |
|
| 172 | + ESP_ERROR_CHECK(i2s_set_pin(I2S_NUM_0, &pins)); |
|
| 173 | + i2s_zero_dma_buffer(I2S_NUM_0); |
|
| 174 | + Serial.println("I2S TX ready"); |
|
| 152 | 175 | } |
| 153 | 176 | |
| 177 | +// ==================== Setup ==================== |
|
| 154 | 178 | void setup() { |
| 155 | 179 | Serial.begin(115200); |
| 156 | - delay(1000); // Wait for Serial monitor |
|
| 180 | + delay(1500); |
|
| 181 | + Serial.println("\n=== ES8311 Melody Player ==="); |
|
| 182 | + |
|
| 183 | + // Enable amplifier if PA_CTRL pin is configured |
|
| 184 | + if (PA_CTRL >= 0) { |
|
| 185 | + pinMode(PA_CTRL, OUTPUT); |
|
| 186 | + digitalWrite(PA_CTRL, HIGH); |
|
| 187 | + Serial.printf("PA_CTRL GPIO%d = HIGH\n", PA_CTRL); |
|
| 188 | + } |
|
| 157 | 189 | |
| 158 | - // === 1. Fire up I2C Bus === |
|
| 159 | 190 | Wire.begin(I2C_SDA, I2C_SCL); |
| 160 | - Wire.setClock(100000); // 100kHz standard speed |
|
| 191 | + Wire.setClock(100000); |
|
| 161 | 192 | |
| 162 | - // === 2. Scan I2C to verify ES8311 is reachable === |
|
| 163 | 193 | Wire.beginTransmission(ES8311_ADDR); |
| 164 | 194 | if (Wire.endTransmission() == 0) { |
| 165 | - Serial.printf("✅ ES8311 found at I2C address 0x%02X\n", ES8311_ADDR); |
|
| 195 | + Serial.printf("ES8311 found at 0x%02X\n", ES8311_ADDR); |
|
| 166 | 196 | } else { |
| 167 | - Serial.printf("❌ ES8311 NOT found at I2C address 0x%02X! Check wiring.\n", ES8311_ADDR); |
|
| 168 | - } |
|
| 169 | - |
|
| 170 | - init_ES8311(); |
|
| 171 | - |
|
| 172 | - // === 2b. Power up DAC and start output path === |
|
| 173 | - start_ES8311_DAC(); |
|
| 174 | - |
|
| 175 | - // === 3. Initialize I2S peripheral (STEREO to match ES8311) === |
|
| 176 | - i2s.setPins(I2S_BCLK, I2S_LRCK, I2S_DOUT, I2S_DIN, I2S_MCLK); |
|
| 177 | - if (!i2s.begin(I2S_MODE_STD, 16000, I2S_DATA_BIT_WIDTH_16BIT, I2S_SLOT_MODE_STEREO, I2S_STD_SLOT_BOTH)) { |
|
| 178 | - Serial.println("❌ Failed to initialize I2S!"); |
|
| 197 | + Serial.printf("ES8311 NOT found at 0x%02X! Check wiring.\n", ES8311_ADDR); |
|
| 179 | 198 | while (1); |
| 180 | 199 | } |
| 181 | - Serial.println("✅ I2S initialized successfully (STEREO)."); |
|
| 200 | + |
|
| 201 | + if (!init_ES8311_DAC()) { while (1); } |
|
| 202 | + setupI2S(); |
|
| 203 | + Serial.println("=== Playing melody ===\n"); |
|
| 182 | 204 | } |
| 183 | 205 | |
| 184 | -// === Melody: "Twinkle Twinkle Little Star" === |
|
| 185 | -// Frequencies in Hz |
|
| 206 | +// ==================== Melody Data ==================== |
|
| 186 | 207 | #define NOTE_C4 262 |
| 187 | 208 | #define NOTE_D4 294 |
| 188 | 209 | #define NOTE_E4 330 |
| ... | ... | @@ -193,120 +214,97 @@ void setup() { |
| 193 | 214 | #define NOTE_C5 523 |
| 194 | 215 | #define NOTE_REST 0 |
| 195 | 216 | |
| 196 | -struct Note { |
|
| 197 | - uint16_t freq; // Hz, 0 = rest |
|
| 198 | - uint16_t duration; // ms |
|
| 199 | -}; |
|
| 217 | +struct Note { uint16_t freq; uint16_t duration; }; |
|
| 200 | 218 | |
| 201 | 219 | const Note melody[] = { |
| 202 | - // Twinkle twinkle little star |
|
| 203 | - {NOTE_C4, 400}, {NOTE_C4, 400}, {NOTE_G4, 400}, {NOTE_G4, 400}, |
|
| 204 | - {NOTE_A4, 400}, {NOTE_A4, 400}, {NOTE_G4, 800}, |
|
| 205 | - // How I wonder what you are |
|
| 206 | - {NOTE_F4, 400}, {NOTE_F4, 400}, {NOTE_E4, 400}, {NOTE_E4, 400}, |
|
| 207 | - {NOTE_D4, 400}, {NOTE_D4, 400}, {NOTE_C4, 800}, |
|
| 208 | - // Up above the world so high |
|
| 209 | - {NOTE_G4, 400}, {NOTE_G4, 400}, {NOTE_F4, 400}, {NOTE_F4, 400}, |
|
| 210 | - {NOTE_E4, 400}, {NOTE_E4, 400}, {NOTE_D4, 800}, |
|
| 211 | - // Like a diamond in the sky |
|
| 212 | - {NOTE_G4, 400}, {NOTE_G4, 400}, {NOTE_F4, 400}, {NOTE_F4, 400}, |
|
| 213 | - {NOTE_E4, 400}, {NOTE_E4, 400}, {NOTE_D4, 800}, |
|
| 214 | - // Twinkle twinkle little star |
|
| 215 | - {NOTE_C4, 400}, {NOTE_C4, 400}, {NOTE_G4, 400}, {NOTE_G4, 400}, |
|
| 216 | - {NOTE_A4, 400}, {NOTE_A4, 400}, {NOTE_G4, 800}, |
|
| 217 | - // How I wonder what you are |
|
| 218 | - {NOTE_F4, 400}, {NOTE_F4, 400}, {NOTE_E4, 400}, {NOTE_E4, 400}, |
|
| 219 | - {NOTE_D4, 400}, {NOTE_D4, 400}, {NOTE_C4, 800}, |
|
| 220 | - // Pause before repeat |
|
| 221 | - {NOTE_REST, 600}, |
|
| 220 | + {NOTE_C4,400},{NOTE_C4,400},{NOTE_G4,400},{NOTE_G4,400}, |
|
| 221 | + {NOTE_A4,400},{NOTE_A4,400},{NOTE_G4,800}, |
|
| 222 | + {NOTE_F4,400},{NOTE_F4,400},{NOTE_E4,400},{NOTE_E4,400}, |
|
| 223 | + {NOTE_D4,400},{NOTE_D4,400},{NOTE_C4,800}, |
|
| 224 | + {NOTE_G4,400},{NOTE_G4,400},{NOTE_F4,400},{NOTE_F4,400}, |
|
| 225 | + {NOTE_E4,400},{NOTE_E4,400},{NOTE_D4,800}, |
|
| 226 | + {NOTE_G4,400},{NOTE_G4,400},{NOTE_F4,400},{NOTE_F4,400}, |
|
| 227 | + {NOTE_E4,400},{NOTE_E4,400},{NOTE_D4,800}, |
|
| 228 | + {NOTE_C4,400},{NOTE_C4,400},{NOTE_G4,400},{NOTE_G4,400}, |
|
| 229 | + {NOTE_A4,400},{NOTE_A4,400},{NOTE_G4,800}, |
|
| 230 | + {NOTE_F4,400},{NOTE_F4,400},{NOTE_E4,400},{NOTE_E4,400}, |
|
| 231 | + {NOTE_D4,400},{NOTE_D4,400},{NOTE_C4,800}, |
|
| 232 | + {NOTE_REST,600}, |
|
| 222 | 233 | }; |
| 223 | 234 | const int melody_len = sizeof(melody) / sizeof(Note); |
| 224 | 235 | |
| 225 | -const int SAMPLE_RATE = 16000; |
|
| 226 | -const int BUFFER_SAMPLES = 256; |
|
| 236 | +// ==================== Audio Generator ==================== |
|
| 237 | +#define BUF_SAMPLES 256 |
|
| 238 | +#define ATTACK_MS 12 |
|
| 239 | +#define RELEASE_MS 15 |
|
| 240 | +#define GAP_MS 4 |
|
| 241 | +#define XFADE_MS 10 |
|
| 227 | 242 | |
| 228 | -// Timing constants (in ms) |
|
| 229 | -const int ATTACK_MS = 12; // note attack ramp |
|
| 230 | -const int RELEASE_MS = 15; // note release ramp |
|
| 231 | -const int GAP_MS = 3; // silence gap between notes |
|
| 232 | -const int XFADE_MS = 8; // frequency crossfade duration |
|
| 233 | - |
|
| 234 | -// State |
|
| 235 | -static float phase = 0.0f; |
|
| 236 | -static uint8_t note_idx = 0; |
|
| 237 | -static uint32_t note_start_ms = 0; |
|
| 238 | -static float prev_freq = melody[0].freq; |
|
| 239 | -static bool first_buffer = true; |
|
| 243 | +static float g_phase = 0.0f; |
|
| 244 | +static uint8_t g_note_idx = 0; |
|
| 245 | +static uint32_t g_note_start = 0; |
|
| 246 | +static float g_prev_freq = melody[0].freq; |
|
| 247 | +static bool g_first = true; |
|
| 240 | 248 | |
| 241 | 249 | void loop() { |
| 242 | - int16_t audio_buffer[BUFFER_SAMPLES * 2]; // stereo L,R interleaved |
|
| 250 | + int16_t buf[BUF_SAMPLES * 2]; |
|
| 243 | 251 | uint32_t now = millis(); |
| 244 | - uint32_t note_elapsed = now - note_start_ms; |
|
| 245 | - Note current = melody[note_idx]; |
|
| 246 | - |
|
| 247 | - // --- Note transition --- |
|
| 248 | - if (note_elapsed >= current.duration + GAP_MS) { |
|
| 249 | - prev_freq = current.freq; |
|
| 250 | - note_idx++; |
|
| 251 | - if (note_idx >= melody_len) note_idx = 0; |
|
| 252 | - note_start_ms = now; |
|
| 253 | - current = melody[note_idx]; |
|
| 254 | - Serial.printf("♪ Note %d: freq=%d Hz, dur=%d ms\n", |
|
| 255 | - note_idx, current.freq, current.duration); |
|
| 256 | - } |
|
| 257 | - // Recalculate note_elapsed AFTER possible transition (fixes envelope bug) |
|
| 258 | - note_elapsed = now - note_start_ms; |
|
| 259 | - |
|
| 260 | - // --- Crossfade frequency between old and new note --- |
|
| 261 | - float xfade_k = (note_elapsed < XFADE_MS) ? (note_elapsed / (float)XFADE_MS) : 1.0f; |
|
| 262 | - float freq = prev_freq * (1.0f - xfade_k) + current.freq * xfade_k; |
|
| 263 | - |
|
| 264 | - // --- Generate audio buffer --- |
|
| 265 | - int gap_samples = GAP_MS * SAMPLE_RATE / 1000; |
|
| 266 | - int attack_samples = ATTACK_MS * SAMPLE_RATE / 1000; |
|
| 267 | - int release_samples = RELEASE_MS * SAMPLE_RATE / 1000; |
|
| 268 | - // current elapsed in samples (estimate, tracking from note_start) |
|
| 269 | - uint32_t sample_offset = (uint32_t)((float)note_elapsed * SAMPLE_RATE / 1000.0f); |
|
| 270 | - uint32_t dur_samples = (uint32_t)((float)current.duration * SAMPLE_RATE / 1000.0f); |
|
| 271 | - |
|
| 272 | - for (int i = 0; i < BUFFER_SAMPLES; i++) { |
|
| 273 | - uint32_t s = sample_offset + i; |
|
| 274 | - int16_t sample; |
|
| 275 | - |
|
| 276 | - // Silence during gap between notes |
|
| 277 | - if (s < (uint32_t)gap_samples) { |
|
| 278 | - sample = 0; |
|
| 279 | - } |
|
| 280 | - // Silence during rest (after crossfade) |
|
| 281 | - else if (current.freq == 0 && note_elapsed >= XFADE_MS) { |
|
| 282 | - sample = 0; |
|
| 283 | - } |
|
| 284 | - else { |
|
| 285 | - // Envelope: attack → sustain → release |
|
| 286 | - float envelope = 0.75f; |
|
| 287 | - uint32_t note_s = s - gap_samples; // sample pos relative to note body |
|
| 288 | - if (note_s < (uint32_t)attack_samples) { |
|
| 289 | - envelope *= (float)note_s / attack_samples; // linear attack |
|
| 290 | - } else if (note_s > dur_samples - release_samples && dur_samples > (uint32_t)(attack_samples + release_samples)) { |
|
| 291 | - uint32_t rel = dur_samples - note_s; |
|
| 292 | - envelope *= (float)rel / release_samples; // linear release |
|
| 293 | - } |
|
| 294 | - |
|
| 295 | - sample = (int16_t)(sinf(phase) * envelope * 28000); |
|
| 296 | - phase += 2.0f * PI * freq / SAMPLE_RATE; |
|
| 297 | - if (phase > 2.0f * PI) phase -= 2.0f * PI; |
|
| 298 | - } |
|
| 299 | - audio_buffer[i * 2] = sample; // Left |
|
| 300 | - audio_buffer[i * 2 + 1] = sample; // Right |
|
| 252 | + |
|
| 253 | + if (g_first) { |
|
| 254 | + g_note_start = now; |
|
| 255 | + g_first = false; |
|
| 256 | + Serial.printf("♪ [0] %d Hz %d ms\n", melody[0].freq, melody[0].duration); |
|
| 301 | 257 | } |
| 302 | 258 | |
| 303 | - size_t written = i2s.write((uint8_t*)audio_buffer, sizeof(audio_buffer)); |
|
| 304 | - if (written != sizeof(audio_buffer)) { |
|
| 305 | - Serial.printf("⚠ I2S write short: %d / %d bytes\n", written, sizeof(audio_buffer)); |
|
| 259 | + uint32_t elapsed = now - g_note_start; |
|
| 260 | + Note cur = melody[g_note_idx]; |
|
| 261 | + |
|
| 262 | + // Note transition |
|
| 263 | + if (elapsed >= cur.duration + GAP_MS) { |
|
| 264 | + g_prev_freq = cur.freq; |
|
| 265 | + g_note_idx = (g_note_idx + 1) % melody_len; |
|
| 266 | + g_note_start = now; |
|
| 267 | + cur = melody[g_note_idx]; |
|
| 268 | + Serial.printf("♪ [%d] %d Hz %d ms\n", g_note_idx, cur.freq, cur.duration); |
|
| 269 | + } |
|
| 270 | + elapsed = now - g_note_start; |
|
| 271 | + |
|
| 272 | + // Crossfade frequency |
|
| 273 | + float xf = (elapsed < XFADE_MS) ? (elapsed / (float)XFADE_MS) : 1.0f; |
|
| 274 | + float freq = g_prev_freq * (1.0f - xf) + cur.freq * xf; |
|
| 275 | + |
|
| 276 | + // Timing |
|
| 277 | + int gap_s = GAP_MS * SAMPLE_RATE / 1000; |
|
| 278 | + int att_s = ATTACK_MS * SAMPLE_RATE / 1000; |
|
| 279 | + int rel_s = RELEASE_MS * SAMPLE_RATE / 1000; |
|
| 280 | + uint32_t off = (uint32_t)(elapsed * SAMPLE_RATE / 1000.0f); |
|
| 281 | + uint32_t dur_s = (uint32_t)(cur.duration * SAMPLE_RATE / 1000.0f); |
|
| 282 | + |
|
| 283 | + for (int i = 0; i < BUF_SAMPLES; i++) { |
|
| 284 | + uint32_t s = off + i; |
|
| 285 | + int16_t smp; |
|
| 286 | + if (s < (uint32_t)gap_s) { |
|
| 287 | + smp = 0; |
|
| 288 | + } else if (cur.freq == 0 && elapsed >= XFADE_MS) { |
|
| 289 | + smp = 0; |
|
| 290 | + } else { |
|
| 291 | + float env = 0.75f; |
|
| 292 | + uint32_t ns = s - gap_s; |
|
| 293 | + if (ns < (uint32_t)att_s) |
|
| 294 | + env *= (float)ns / att_s; |
|
| 295 | + else if (ns > dur_s - rel_s && dur_s > (uint32_t)(att_s + rel_s)) |
|
| 296 | + env *= (float)(dur_s - ns) / rel_s; |
|
| 297 | + smp = (int16_t)(sinf(g_phase) * env * 28000); |
|
| 298 | + g_phase += 2.0f * PI * freq / SAMPLE_RATE; |
|
| 299 | + if (g_phase > 2.0f * PI) g_phase -= 2.0f * PI; |
|
| 300 | + } |
|
| 301 | + buf[i * 2] = smp; |
|
| 302 | + buf[i * 2 + 1] = smp; |
|
| 306 | 303 | } |
| 307 | 304 | |
| 308 | - if (first_buffer) { |
|
| 309 | - Serial.println("▶ Melody started: Twinkle Twinkle Little Star"); |
|
| 310 | - first_buffer = false; |
|
| 305 | + size_t written = 0; |
|
| 306 | + esp_err_t err = i2s_write(I2S_NUM_0, buf, sizeof(buf), &written, portMAX_DELAY); |
|
| 307 | + if (err != ESP_OK || written != sizeof(buf)) { |
|
| 308 | + Serial.printf("I2S err=%d written=%d\n", err, written); |
|
| 311 | 309 | } |
| 312 | 310 | } |
| ... | ... | \ No newline at end of file |
Chip-cn-dat/everest-semi-dat/ES8311-dat/ES8311-SDK-dat/test/ES8311-code-spk5/ES8311-code-spk5.ino
| ... | ... | @@ -0,0 +1,218 @@ |
| 1 | +/* |
|
| 2 | + * ES8311-code-spk5.ino |
|
| 3 | + * |
|
| 4 | + * Minimal Arduino sketch that reuses es8311.c / es8311.h from the |
|
| 5 | + * official ESP-IDF driver. Both files live in this same folder and |
|
| 6 | + * are auto-compiled by the Arduino IDE. |
|
| 7 | + * |
|
| 8 | + * The init sequence follows es8311.c exactly: |
|
| 9 | + * es8311_codec_init() → es8311_start(ES_MODULE_DAC) |
|
| 10 | + * |
|
| 11 | + * I2C uses Arduino Wire instead of the ESP-IDF i2c_driver. |
|
| 12 | + * |
|
| 13 | + * Wiring (from ES8311-dat): |
|
| 14 | + * GPIO 4 → SCL GPIO 5 → SDA |
|
| 15 | + * GPIO 6 → MCLK GPIO 11 → DIN (ESP32 DOUT → ES8311 SDIN) |
|
| 16 | + * GPIO 12 → LRCK GPIO 14 → BCLK |
|
| 17 | + */ |
|
| 18 | + |
|
| 19 | +#include <Wire.h> |
|
| 20 | +#include <driver/i2s.h> |
|
| 21 | +#include "es8311.h" // register constants |
|
| 22 | + |
|
| 23 | +// ==================== Pins ==================== |
|
| 24 | +#define I2C_SDA 5 |
|
| 25 | +#define I2C_SCL 4 |
|
| 26 | +#define I2S_MCLK 6 |
|
| 27 | +#define I2S_BCLK 14 |
|
| 28 | +#define I2S_LRCK 12 |
|
| 29 | +#define I2S_DOUT 11 // → ES8311 SDIN |
|
| 30 | +#define I2S_DIN 13 // unused |
|
| 31 | + |
|
| 32 | +#define PA_CTRL -1 |
|
| 33 | +#define SAMPLE_RATE 16000 |
|
| 34 | +#define MCLK_HZ (SAMPLE_RATE * 256) |
|
| 35 | + |
|
| 36 | +// ==================== I2C helpers ==================== |
|
| 37 | +static bool w(uint8_t r, uint8_t v) { |
|
| 38 | + Wire.beginTransmission(0x18); |
|
| 39 | + Wire.write(r); Wire.write(v); |
|
| 40 | + return Wire.endTransmission() == 0; |
|
| 41 | +} |
|
| 42 | +static uint8_t r(uint8_t r) { |
|
| 43 | + Wire.beginTransmission(0x18); Wire.write(r); |
|
| 44 | + Wire.endTransmission(false); |
|
| 45 | + Wire.requestFrom((uint16_t)0x18, (uint8_t)1); |
|
| 46 | + return Wire.available() ? Wire.read() : 0xFF; |
|
| 47 | +} |
|
| 48 | + |
|
| 49 | +// ==================== Clock coefficient (16k, MCLK=4.096M) ==================== |
|
| 50 | +// From coeff_div[]: {4096000,16000, pre=1,mult=1, adc=1,dac=1, |
|
| 51 | +// fs=0, lrch=0,lrcl=0xFF, bck=4, osr=16} |
|
| 52 | +static void set_coeff() { |
|
| 53 | + w(ES8311_CLK_MANAGER_REG02, 0x00); // pre_div=1, pre_multi=1 |
|
| 54 | + w(ES8311_CLK_MANAGER_REG03, 0x10); // fs=0, adc_osr=16 |
|
| 55 | + w(ES8311_CLK_MANAGER_REG04, 0x10); // dac_osr=16 |
|
| 56 | + w(ES8311_CLK_MANAGER_REG05, 0x00); // adc=1, dac=1 |
|
| 57 | + w(ES8311_CLK_MANAGER_REG06, 0x03); // bclk_div=4 |
|
| 58 | + w(ES8311_CLK_MANAGER_REG07, 0x00); // lrck_h=0 |
|
| 59 | + w(ES8311_CLK_MANAGER_REG08, 0xFF); // lrck_l=0xFF |
|
| 60 | +} |
|
| 61 | + |
|
| 62 | +// ==================== ES8311 init ==================== |
|
| 63 | +// Follows es8311_codec_init() from es8311.c line-for-line |
|
| 64 | +bool es8311_init() { |
|
| 65 | + // Pre-reset |
|
| 66 | + w(ES8311_CLK_MANAGER_REG01, 0x30); |
|
| 67 | + w(ES8311_CLK_MANAGER_REG02, 0x00); |
|
| 68 | + w(ES8311_CLK_MANAGER_REG03, 0x10); |
|
| 69 | + w(ES8311_ADC_REG16, 0x24); |
|
| 70 | + w(ES8311_CLK_MANAGER_REG04, 0x10); |
|
| 71 | + w(ES8311_CLK_MANAGER_REG05, 0x00); |
|
| 72 | + w(ES8311_SYSTEM_REG0B, 0x00); |
|
| 73 | + w(ES8311_SYSTEM_REG0C, 0x00); |
|
| 74 | + w(ES8311_SYSTEM_REG10, 0x1F); |
|
| 75 | + w(ES8311_SYSTEM_REG11, 0x7F); |
|
| 76 | + |
|
| 77 | + if (!w(ES8311_RESET_REG00, 0x80)) return false; |
|
| 78 | + delay(20); |
|
| 79 | + |
|
| 80 | + // Slave mode |
|
| 81 | + w(ES8311_RESET_REG00, r(ES8311_RESET_REG00) & 0xBF); |
|
| 82 | + |
|
| 83 | + // All clocks ON |
|
| 84 | + w(ES8311_CLK_MANAGER_REG01, 0x3F); |
|
| 85 | + |
|
| 86 | + // MCLK pin (clear bit7) |
|
| 87 | + w(ES8311_CLK_MANAGER_REG01, r(ES8311_CLK_MANAGER_REG01) & 0x7F); |
|
| 88 | + |
|
| 89 | + set_coeff(); |
|
| 90 | + |
|
| 91 | + // MCLK not inverted, BCLK not inverted |
|
| 92 | + w(ES8311_CLK_MANAGER_REG01, r(ES8311_CLK_MANAGER_REG01) & ~0x40); |
|
| 93 | + w(ES8311_CLK_MANAGER_REG06, r(ES8311_CLK_MANAGER_REG06) & ~0x20); |
|
| 94 | + |
|
| 95 | + w(ES8311_SYSTEM_REG13, 0x10); |
|
| 96 | + w(ES8311_ADC_REG1B, 0x0A); |
|
| 97 | + w(ES8311_ADC_REG1C, 0x6A); |
|
| 98 | + w(ES8311_GPIO_REG44, 0x08); |
|
| 99 | + return true; |
|
| 100 | +} |
|
| 101 | + |
|
| 102 | +// ==================== DAC start ==================== |
|
| 103 | +// Follows es8311_start(ES_MODULE_DAC) from es8311.c |
|
| 104 | +void es8311_start_dac() { |
|
| 105 | + // Unmute DAC (clear bit6 in reg09) |
|
| 106 | + w(ES8311_SDPIN_REG09, r(ES8311_SDPIN_REG09) & 0xBF); |
|
| 107 | + // Unmute ADC (clear bit6 in reg0A) |
|
| 108 | + w(ES8311_SDPOUT_REG0A, r(ES8311_SDPOUT_REG0A) & 0xBF); |
|
| 109 | + |
|
| 110 | + w(ES8311_DAC_REG32, 0xBF); // 0 dB |
|
| 111 | + w(ES8311_ADC_REG17, 0xBF); |
|
| 112 | + w(ES8311_SYSTEM_REG0E, 0x02); |
|
| 113 | + w(ES8311_SYSTEM_REG12, 0x00); |
|
| 114 | + w(ES8311_SYSTEM_REG14, 0x1A); // analog mic, not DMIC |
|
| 115 | + w(ES8311_SYSTEM_REG0D, 0x01); |
|
| 116 | + delay(5); |
|
| 117 | + w(ES8311_ADC_REG15, 0x40); |
|
| 118 | + w(ES8311_DAC_REG37, 0x48); |
|
| 119 | + w(ES8311_GP_REG45, 0x00); |
|
| 120 | +} |
|
| 121 | + |
|
| 122 | +// ==================== I2S ==================== |
|
| 123 | +void setup_i2s() { |
|
| 124 | + i2s_config_t c = { |
|
| 125 | + .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), |
|
| 126 | + .sample_rate = SAMPLE_RATE, |
|
| 127 | + .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, |
|
| 128 | + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, |
|
| 129 | + .communication_format = I2S_COMM_FORMAT_STAND_I2S, |
|
| 130 | + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, |
|
| 131 | + .dma_buf_count = 4, |
|
| 132 | + .dma_buf_len = 256, |
|
| 133 | + .use_apll = true, |
|
| 134 | + .tx_desc_auto_clear = true, |
|
| 135 | + .fixed_mclk = MCLK_HZ, |
|
| 136 | + }; |
|
| 137 | + i2s_pin_config_t p = { |
|
| 138 | + .bck_io_num = I2S_BCLK, |
|
| 139 | + .ws_io_num = I2S_LRCK, |
|
| 140 | + .data_out_num = I2S_DOUT, |
|
| 141 | + .data_in_num = I2S_PIN_NO_CHANGE, |
|
| 142 | + }; |
|
| 143 | + ESP_ERROR_CHECK(i2s_driver_install(I2S_NUM_0, &c, 0, NULL)); |
|
| 144 | + ESP_ERROR_CHECK(i2s_set_pin(I2S_NUM_0, &p)); |
|
| 145 | + i2s_zero_dma_buffer(I2S_NUM_0); |
|
| 146 | +} |
|
| 147 | + |
|
| 148 | +// ==================== Register dump ==================== |
|
| 149 | +void dump() { |
|
| 150 | + Serial.println("--- ES8311 regs ---"); |
|
| 151 | + uint8_t regs[] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08, |
|
| 152 | + 0x09,0x0A,0x0D,0x0E,0x12,0x14,0x15,0x31,0x32,0x37,0x44,0x45}; |
|
| 153 | + for (int i = 0; i < (int)(sizeof(regs)/sizeof(regs[0])); i++) |
|
| 154 | + Serial.printf(" [0x%02X] = 0x%02X\n", regs[i], r(regs[i])); |
|
| 155 | +} |
|
| 156 | + |
|
| 157 | +// ==================== Melody ==================== |
|
| 158 | +#define BUF_SZ 256 |
|
| 159 | +#define N8(f) {f,800} |
|
| 160 | +#define N4(f) {f,400} |
|
| 161 | +#define RST {0,600} |
|
| 162 | + |
|
| 163 | +static const struct { uint16_t f, d; } mel[] = { |
|
| 164 | + N4(262),N4(262),N4(392),N4(392),N4(440),N4(440),N8(392), |
|
| 165 | + N4(349),N4(349),N4(330),N4(330),N4(294),N4(294),N8(262), |
|
| 166 | + N8(392),N8(349),N8(330),N8(294), |
|
| 167 | + N4(262),N4(262),N4(392),N4(392),N4(440),N4(440),N8(392), |
|
| 168 | + N4(349),N4(349),N4(330),N4(330),N4(294),N4(294),N8(262), |
|
| 169 | + RST, |
|
| 170 | +}; |
|
| 171 | +static const int N = sizeof(mel)/sizeof(mel[0]); |
|
| 172 | + |
|
| 173 | +static float ph = 0; |
|
| 174 | +static uint8_t ix = 0; |
|
| 175 | +static uint32_t t0 = 0; |
|
| 176 | +static bool fst = true; |
|
| 177 | + |
|
| 178 | +// ==================== Setup ==================== |
|
| 179 | +void setup() { |
|
| 180 | + Serial.begin(115200); delay(1500); |
|
| 181 | + Serial.println("\n=== spk5 ==="); |
|
| 182 | + |
|
| 183 | + if (PA_CTRL >= 0) { pinMode(PA_CTRL, OUTPUT); digitalWrite(PA_CTRL, HIGH); } |
|
| 184 | + |
|
| 185 | + Wire.begin(I2C_SDA, I2C_SCL); Wire.setClock(100000); |
|
| 186 | + Wire.beginTransmission(0x18); |
|
| 187 | + if (Wire.endTransmission()) { Serial.println("No ES8311!"); while (1); } |
|
| 188 | + Serial.println("ES8311 found"); |
|
| 189 | + |
|
| 190 | + if (!es8311_init()) { Serial.println("Init FAIL"); while (1); } |
|
| 191 | + es8311_start_dac(); |
|
| 192 | + dump(); |
|
| 193 | + setup_i2s(); |
|
| 194 | + Serial.println("=== play ===\n"); |
|
| 195 | +} |
|
| 196 | + |
|
| 197 | +// ==================== Loop ==================== |
|
| 198 | +void loop() { |
|
| 199 | + int16_t buf[BUF_SZ * 2]; |
|
| 200 | + uint32_t now = millis(); |
|
| 201 | + if (fst) { t0 = now; fst = false; } |
|
| 202 | + |
|
| 203 | + uint32_t el = now - t0; |
|
| 204 | + if (el >= mel[ix].d + 4) { |
|
| 205 | + ix = (ix + 1) % N; |
|
| 206 | + t0 = now; el = 0; |
|
| 207 | + Serial.printf("♪ %d Hz\n", mel[ix].f); |
|
| 208 | + } |
|
| 209 | + |
|
| 210 | + for (int i = 0; i < BUF_SZ; i++) { |
|
| 211 | + int16_t s = mel[ix].f ? (int16_t)(sinf(ph) * 24000) : 0; |
|
| 212 | + ph += 2 * PI * mel[ix].f / SAMPLE_RATE; |
|
| 213 | + if (ph > 2 * PI) ph -= 2 * PI; |
|
| 214 | + buf[i*2] = buf[i*2+1] = s; |
|
| 215 | + } |
|
| 216 | + size_t w = 0; |
|
| 217 | + i2s_write(I2S_NUM_0, buf, sizeof(buf), &w, portMAX_DELAY); |
|
| 218 | +} |
Chip-cn-dat/everest-semi-dat/ES8311-dat/ES8311-SDK-dat/test/ES8311-code-spk5/es8311.c
| ... | ... | @@ -0,0 +1,749 @@ |
| 1 | +/* |
|
| 2 | + * ESPRESSIF MIT License |
|
| 3 | + * |
|
| 4 | + * Copyright (c) 2019 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD> |
|
| 5 | + * |
|
| 6 | + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, |
|
| 7 | + * it is free of charge, to any person obtaining a copy of this software and associated |
|
| 8 | + * documentation files (the "Software"), to deal in the Software without restriction, including |
|
| 9 | + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
| 10 | + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished |
|
| 11 | + * to do so, subject to the following conditions: |
|
| 12 | + * |
|
| 13 | + * The above copyright notice and this permission notice shall be included in all copies or |
|
| 14 | + * substantial portions of the Software. |
|
| 15 | + * |
|
| 16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
| 17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
|
| 18 | + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
| 19 | + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
|
| 20 | + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
| 21 | + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
| 22 | + * |
|
| 23 | + */ |
|
| 24 | + |
|
| 25 | +#include <string.h> |
|
| 26 | +#include "driver/i2c.h" |
|
| 27 | +#include "board.h" |
|
| 28 | +#include "esp_log.h" |
|
| 29 | +#include "es8311.h" |
|
| 30 | + |
|
| 31 | +/* ES8311 address |
|
| 32 | + * 0x32:CE=1;0x30:CE=0 |
|
| 33 | + */ |
|
| 34 | +#define ES8311_ADDR 0x30 |
|
| 35 | + |
|
| 36 | +/* |
|
| 37 | + * to define the clock soure of MCLK |
|
| 38 | + */ |
|
| 39 | +#define FROM_MCLK_PIN 0 |
|
| 40 | +#define FROM_SCLK_PIN 1 |
|
| 41 | +#define MCLK_SOURCE 0 |
|
| 42 | + |
|
| 43 | +/* |
|
| 44 | + * to define whether to reverse the clock |
|
| 45 | + */ |
|
| 46 | +#define INVERT_MCLK 0 // do not invert |
|
| 47 | +#define INVERT_SCLK 0 |
|
| 48 | + |
|
| 49 | +#define IS_DMIC 0 // Is it a digital microphone |
|
| 50 | + |
|
| 51 | +#define MCLK_DIV_FRE 256 |
|
| 52 | + |
|
| 53 | +/* |
|
| 54 | + * i2c default configuration |
|
| 55 | + */ |
|
| 56 | +static i2c_config_t es_i2c_cfg = { |
|
| 57 | + .mode = I2C_MODE_MASTER, |
|
| 58 | + .sda_pullup_en = GPIO_PULLUP_ENABLE, |
|
| 59 | + .scl_pullup_en = GPIO_PULLUP_ENABLE, |
|
| 60 | + .master.clk_speed = 100000 |
|
| 61 | +}; |
|
| 62 | + |
|
| 63 | +/* |
|
| 64 | + * operate function of codec |
|
| 65 | + */ |
|
| 66 | +audio_hal_func_t AUDIO_CODEC_ES8311_DEFAULT_HANDLE = { |
|
| 67 | + .audio_codec_initialize = es8311_codec_init, |
|
| 68 | + .audio_codec_deinitialize = es8311_codec_deinit, |
|
| 69 | + .audio_codec_ctrl = es8311_codec_ctrl_state, |
|
| 70 | + .audio_codec_config_iface = es8311_codec_config_i2s, |
|
| 71 | + .audio_codec_set_mute = es8311_set_voice_mute, |
|
| 72 | + .audio_codec_set_volume = es8311_codec_set_voice_volume, |
|
| 73 | + .audio_codec_get_volume = es8311_codec_get_voice_volume, |
|
| 74 | +}; |
|
| 75 | + |
|
| 76 | +/* |
|
| 77 | + * Clock coefficient structer |
|
| 78 | + */ |
|
| 79 | +struct _coeff_div { |
|
| 80 | + uint32_t mclk; /* mclk frequency */ |
|
| 81 | + uint32_t rate; /* sample rate */ |
|
| 82 | + uint8_t pre_div; /* the pre divider with range from 1 to 8 */ |
|
| 83 | + uint8_t pre_multi; /* the pre multiplier with x1, x2, x4 and x8 selection */ |
|
| 84 | + uint8_t adc_div; /* adcclk divider */ |
|
| 85 | + uint8_t dac_div; /* dacclk divider */ |
|
| 86 | + uint8_t fs_mode; /* double speed or single speed, =0, ss, =1, ds */ |
|
| 87 | + uint8_t lrck_h; /* adclrck divider and daclrck divider */ |
|
| 88 | + uint8_t lrck_l; |
|
| 89 | + uint8_t bclk_div; /* sclk divider */ |
|
| 90 | + uint8_t adc_osr; /* adc osr */ |
|
| 91 | + uint8_t dac_osr; /* dac osr */ |
|
| 92 | +}; |
|
| 93 | + |
|
| 94 | +/* codec hifi mclk clock divider coefficients */ |
|
| 95 | +static const struct _coeff_div coeff_div[] = { |
|
| 96 | + //mclk rate pre_div mult adc_div dac_div fs_mode lrch lrcl bckdiv osr |
|
| 97 | + /* 8k */ |
|
| 98 | + {12288000, 8000 , 0x06, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 99 | + {18432000, 8000 , 0x03, 0x02, 0x03, 0x03, 0x00, 0x05, 0xff, 0x18, 0x10, 0x10}, |
|
| 100 | + {16384000, 8000 , 0x08, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 101 | + {8192000 , 8000 , 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 102 | + {6144000 , 8000 , 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 103 | + {4096000 , 8000 , 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 104 | + {3072000 , 8000 , 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 105 | + {2048000 , 8000 , 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 106 | + {1536000 , 8000 , 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 107 | + {1024000 , 8000 , 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 108 | + |
|
| 109 | + /* 11.025k */ |
|
| 110 | + {11289600, 11025, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 111 | + {5644800 , 11025, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 112 | + {2822400 , 11025, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 113 | + {1411200 , 11025, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 114 | + |
|
| 115 | + /* 12k */ |
|
| 116 | + {12288000, 12000, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 117 | + {6144000 , 12000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 118 | + {3072000 , 12000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 119 | + {1536000 , 12000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 120 | + |
|
| 121 | + /* 16k */ |
|
| 122 | + {12288000, 16000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 123 | + {18432000, 16000, 0x03, 0x02, 0x03, 0x03, 0x00, 0x02, 0xff, 0x0c, 0x10, 0x10}, |
|
| 124 | + {16384000, 16000, 0x04, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 125 | + {8192000 , 16000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 126 | + {6144000 , 16000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 127 | + {4096000 , 16000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 128 | + {3072000 , 16000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 129 | + {2048000 , 16000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 130 | + {1536000 , 16000, 0x03, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 131 | + {1024000 , 16000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 132 | + |
|
| 133 | + /* 22.05k */ |
|
| 134 | + {11289600, 22050, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 135 | + {5644800 , 22050, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 136 | + {2822400 , 22050, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 137 | + {1411200 , 22050, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 138 | + |
|
| 139 | + /* 24k */ |
|
| 140 | + {12288000, 24000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 141 | + {18432000, 24000, 0x03, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 142 | + {6144000 , 24000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 143 | + {3072000 , 24000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 144 | + {1536000 , 24000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 145 | + |
|
| 146 | + /* 32k */ |
|
| 147 | + {12288000, 32000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 148 | + {18432000, 32000, 0x03, 0x04, 0x03, 0x03, 0x00, 0x02, 0xff, 0x0c, 0x10, 0x10}, |
|
| 149 | + {16384000, 32000, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 150 | + {8192000 , 32000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 151 | + {6144000 , 32000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 152 | + {4096000 , 32000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 153 | + {3072000 , 32000, 0x03, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 154 | + {2048000 , 32000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 155 | + {1536000 , 32000, 0x03, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, |
|
| 156 | + {1024000 , 32000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 157 | + |
|
| 158 | + /* 44.1k */ |
|
| 159 | + {11289600, 44100, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 160 | + {5644800 , 44100, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 161 | + {2822400 , 44100, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 162 | + {1411200 , 44100, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 163 | + |
|
| 164 | + /* 48k */ |
|
| 165 | + {12288000, 48000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 166 | + {18432000, 48000, 0x03, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 167 | + {6144000 , 48000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 168 | + {3072000 , 48000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 169 | + {1536000 , 48000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 170 | + |
|
| 171 | + /* 64k */ |
|
| 172 | + {12288000, 64000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 173 | + {18432000, 64000, 0x03, 0x04, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10}, |
|
| 174 | + {16384000, 64000, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 175 | + {8192000 , 64000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 176 | + {6144000 , 64000, 0x01, 0x04, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10}, |
|
| 177 | + {4096000 , 64000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 178 | + {3072000 , 64000, 0x01, 0x08, 0x03, 0x03, 0x01, 0x01, 0x7f, 0x06, 0x10, 0x10}, |
|
| 179 | + {2048000 , 64000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 180 | + {1536000 , 64000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0xbf, 0x03, 0x18, 0x18}, |
|
| 181 | + {1024000 , 64000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, |
|
| 182 | + |
|
| 183 | + /* 88.2k */ |
|
| 184 | + {11289600, 88200, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 185 | + {5644800 , 88200, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 186 | + {2822400 , 88200, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 187 | + {1411200 , 88200, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, |
|
| 188 | + |
|
| 189 | + /* 96k */ |
|
| 190 | + {12288000, 96000, 0x01, 0x02, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 191 | + {18432000, 96000, 0x03, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 192 | + {6144000 , 96000, 0x01, 0x04, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 193 | + {3072000 , 96000, 0x01, 0x08, 0x01, 0x01, 0x00, 0x00, 0xff, 0x04, 0x10, 0x10}, |
|
| 194 | + {1536000 , 96000, 0x01, 0x08, 0x01, 0x01, 0x01, 0x00, 0x7f, 0x02, 0x10, 0x10}, |
|
| 195 | +}; |
|
| 196 | + |
|
| 197 | +static char *TAG = "DRV8311"; |
|
| 198 | + |
|
| 199 | +#define ES_ASSERT(a, format, b, ...) \ |
|
| 200 | + if ((a) != 0) { \ |
|
| 201 | + ESP_LOGE(TAG, format, ##__VA_ARGS__); \ |
|
| 202 | + return b;\ |
|
| 203 | + } |
|
| 204 | + |
|
| 205 | +static int es8311_write_reg(uint8_t reg_addr, uint8_t data) |
|
| 206 | +{ |
|
| 207 | + int res = 0; |
|
| 208 | + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); |
|
| 209 | + res |= i2c_master_start(cmd); |
|
| 210 | + res |= i2c_master_write_byte(cmd, ES8311_ADDR, 1 /*ACK_CHECK_EN*/); |
|
| 211 | + res |= i2c_master_write_byte(cmd, reg_addr, 1 /*ACK_CHECK_EN*/); |
|
| 212 | + res |= i2c_master_write_byte(cmd, data, 1 /*ACK_CHECK_EN*/); |
|
| 213 | + res |= i2c_master_stop(cmd); |
|
| 214 | + res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_RATE_MS); |
|
| 215 | + i2c_cmd_link_delete(cmd); |
|
| 216 | + ES_ASSERT(res, "Es8311 Write Reg error", -1); |
|
| 217 | + return res; |
|
| 218 | +} |
|
| 219 | + |
|
| 220 | +static int es8311_read_reg(uint8_t reg_addr) |
|
| 221 | +{ |
|
| 222 | + uint8_t data; |
|
| 223 | + int res = 0; |
|
| 224 | + i2c_cmd_handle_t cmd = i2c_cmd_link_create(); |
|
| 225 | + |
|
| 226 | + res |= i2c_master_start(cmd); |
|
| 227 | + res |= i2c_master_write_byte(cmd, ES8311_ADDR, 1 /*ACK_CHECK_EN*/); |
|
| 228 | + res |= i2c_master_write_byte(cmd, reg_addr, 1 /*ACK_CHECK_EN*/); |
|
| 229 | + res |= i2c_master_stop(cmd); |
|
| 230 | + res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_RATE_MS); |
|
| 231 | + i2c_cmd_link_delete(cmd); |
|
| 232 | + |
|
| 233 | + cmd = i2c_cmd_link_create(); |
|
| 234 | + res |= i2c_master_start(cmd); |
|
| 235 | + res |= i2c_master_write_byte(cmd, ES8311_ADDR | 0x01, 1 /*ACK_CHECK_EN*/); |
|
| 236 | + res |= i2c_master_read_byte(cmd, &data, 0x01 /*NACK_VAL*/); |
|
| 237 | + res |= i2c_master_stop(cmd); |
|
| 238 | + res |= i2c_master_cmd_begin(0, cmd, 1000 / portTICK_RATE_MS); |
|
| 239 | + i2c_cmd_link_delete(cmd); |
|
| 240 | + |
|
| 241 | + ES_ASSERT(res, "Es8311 Read Reg error", -1); |
|
| 242 | + return (int)data; |
|
| 243 | +} |
|
| 244 | + |
|
| 245 | +static int i2c_init() |
|
| 246 | +{ |
|
| 247 | + int res = 0; |
|
| 248 | + get_i2c_pins(I2C_NUM_0, &es_i2c_cfg); |
|
| 249 | + res |= i2c_param_config(I2C_NUM_0, &es_i2c_cfg); |
|
| 250 | + res |= i2c_driver_install(I2C_NUM_0, es_i2c_cfg.mode, 0, 0, 0); |
|
| 251 | + ES_ASSERT(res, "i2c_init error", -1); |
|
| 252 | + return res; |
|
| 253 | +} |
|
| 254 | + |
|
| 255 | +/* |
|
| 256 | +* look for the coefficient in coeff_div[] table |
|
| 257 | +*/ |
|
| 258 | +static int get_coeff(uint32_t mclk, uint32_t rate) |
|
| 259 | +{ |
|
| 260 | + for (int i = 0; i < (sizeof(coeff_div) / sizeof(coeff_div[0])); i++) { |
|
| 261 | + if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk) |
|
| 262 | + return i; |
|
| 263 | + } |
|
| 264 | + return -1; |
|
| 265 | +} |
|
| 266 | + |
|
| 267 | +/* |
|
| 268 | +* set es8311 dac mute or not |
|
| 269 | +* if mute = 0, dac un-mute |
|
| 270 | +* if mute = 1, dac mute |
|
| 271 | +*/ |
|
| 272 | +static void es8311_mute(int mute) |
|
| 273 | +{ |
|
| 274 | + uint8_t regv; |
|
| 275 | + ESP_LOGI(TAG, "Enter into es8311_mute(), mute = %d\n", mute); |
|
| 276 | + regv = es8311_read_reg(ES8311_DAC_REG31) & 0x9f; |
|
| 277 | + if (mute) { |
|
| 278 | + es8311_write_reg(ES8311_SYSTEM_REG12, 0x02); |
|
| 279 | + es8311_write_reg(ES8311_DAC_REG31, regv | 0x60); |
|
| 280 | + es8311_write_reg(ES8311_DAC_REG32, 0x00); |
|
| 281 | + es8311_write_reg(ES8311_DAC_REG37, 0x08); |
|
| 282 | + } else { |
|
| 283 | + es8311_write_reg(ES8311_DAC_REG31, regv); |
|
| 284 | + es8311_write_reg(ES8311_SYSTEM_REG12, 0x00); |
|
| 285 | + } |
|
| 286 | +} |
|
| 287 | + |
|
| 288 | +/* |
|
| 289 | +* set es8311 into suspend mode |
|
| 290 | +*/ |
|
| 291 | +static void es8311_suspend(void) |
|
| 292 | +{ |
|
| 293 | + ESP_LOGI(TAG, "Enter into es8311_suspend()"); |
|
| 294 | + es8311_write_reg(ES8311_DAC_REG32, 0x00); |
|
| 295 | + es8311_write_reg(ES8311_ADC_REG17, 0x00); |
|
| 296 | + es8311_write_reg(ES8311_SYSTEM_REG0E, 0xFF); |
|
| 297 | + es8311_write_reg(ES8311_SYSTEM_REG12, 0x02); |
|
| 298 | + es8311_write_reg(ES8311_SYSTEM_REG14, 0x00); |
|
| 299 | + es8311_write_reg(ES8311_SYSTEM_REG0D, 0xFA); |
|
| 300 | + es8311_write_reg(ES8311_ADC_REG15, 0x00); |
|
| 301 | + es8311_write_reg(ES8311_DAC_REG37, 0x08); |
|
| 302 | + es8311_write_reg(ES8311_GP_REG45, 0x01); |
|
| 303 | +} |
|
| 304 | + |
|
| 305 | +/* |
|
| 306 | +* enable pa power |
|
| 307 | +*/ |
|
| 308 | +void es8311_pa_power(bool enable) |
|
| 309 | +{ |
|
| 310 | + gpio_config_t io_conf; |
|
| 311 | + memset(&io_conf, 0, sizeof(io_conf)); |
|
| 312 | + io_conf.intr_type = GPIO_PIN_INTR_DISABLE; |
|
| 313 | + io_conf.mode = GPIO_MODE_OUTPUT; |
|
| 314 | + io_conf.pin_bit_mask = BIT(get_pa_enable_gpio()); |
|
| 315 | + io_conf.pull_down_en = 0; |
|
| 316 | + io_conf.pull_up_en = 0; |
|
| 317 | + gpio_config(&io_conf); |
|
| 318 | + if (enable) { |
|
| 319 | + gpio_set_level(get_pa_enable_gpio(), 1); |
|
| 320 | + } else { |
|
| 321 | + gpio_set_level(get_pa_enable_gpio(), 0); |
|
| 322 | + } |
|
| 323 | +} |
|
| 324 | + |
|
| 325 | +esp_err_t es8311_codec_init(audio_hal_codec_config_t *codec_cfg) |
|
| 326 | +{ |
|
| 327 | + uint8_t datmp, regv; |
|
| 328 | + int coeff; |
|
| 329 | + esp_err_t ret = ESP_OK; |
|
| 330 | + i2c_init(); // ESP32 in master mode |
|
| 331 | + |
|
| 332 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, 0x30); |
|
| 333 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, 0x00); |
|
| 334 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG03, 0x10); |
|
| 335 | + ret |= es8311_write_reg(ES8311_ADC_REG16, 0x24); |
|
| 336 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG04, 0x10); |
|
| 337 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG05, 0x00); |
|
| 338 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG0B, 0x00); |
|
| 339 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG0C, 0x00); |
|
| 340 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG10, 0x1F); |
|
| 341 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG11, 0x7F); |
|
| 342 | + ret |= es8311_write_reg(ES8311_RESET_REG00, 0x80); |
|
| 343 | + /* |
|
| 344 | + * Set Codec into Master or Slave mode |
|
| 345 | + */ |
|
| 346 | + regv = es8311_read_reg(ES8311_RESET_REG00); |
|
| 347 | + /* |
|
| 348 | + * Set master/slave audio interface |
|
| 349 | + */ |
|
| 350 | + audio_hal_codec_i2s_iface_t *i2s_cfg = &(codec_cfg->i2s_iface); |
|
| 351 | + switch (i2s_cfg->mode) { |
|
| 352 | + case AUDIO_HAL_MODE_MASTER: /* MASTER MODE */ |
|
| 353 | + ESP_LOGI(TAG, "ES8311 in Master mode"); |
|
| 354 | + regv |= 0x40; |
|
| 355 | + break; |
|
| 356 | + case AUDIO_HAL_MODE_SLAVE: /* SLAVE MODE */ |
|
| 357 | + ESP_LOGI(TAG, "ES8311 in Slave mode"); |
|
| 358 | + regv &= 0xBF; |
|
| 359 | + break; |
|
| 360 | + default: |
|
| 361 | + regv &= 0xBF; |
|
| 362 | + } |
|
| 363 | + ret |= es8311_write_reg(ES8311_RESET_REG00, regv); |
|
| 364 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, 0x3F); |
|
| 365 | + /* |
|
| 366 | + * Select clock source for internal mclk |
|
| 367 | + */ |
|
| 368 | + switch (MCLK_SOURCE) { |
|
| 369 | + case FROM_MCLK_PIN: |
|
| 370 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); |
|
| 371 | + regv &= 0x7F; |
|
| 372 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); |
|
| 373 | + break; |
|
| 374 | + case FROM_SCLK_PIN: |
|
| 375 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); |
|
| 376 | + regv |= 0x80; |
|
| 377 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); |
|
| 378 | + break; |
|
| 379 | + default: |
|
| 380 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); |
|
| 381 | + regv &= 0x7F; |
|
| 382 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); |
|
| 383 | + break; |
|
| 384 | + } |
|
| 385 | + int sample_fre = 0; |
|
| 386 | + int mclk_fre = 0; |
|
| 387 | + switch (i2s_cfg->samples) { |
|
| 388 | + case AUDIO_HAL_08K_SAMPLES: |
|
| 389 | + sample_fre = 8000; |
|
| 390 | + break; |
|
| 391 | + case AUDIO_HAL_11K_SAMPLES: |
|
| 392 | + sample_fre = 11025; |
|
| 393 | + break; |
|
| 394 | + case AUDIO_HAL_16K_SAMPLES: |
|
| 395 | + sample_fre = 16000; |
|
| 396 | + break; |
|
| 397 | + case AUDIO_HAL_22K_SAMPLES: |
|
| 398 | + sample_fre = 22050; |
|
| 399 | + break; |
|
| 400 | + case AUDIO_HAL_24K_SAMPLES: |
|
| 401 | + sample_fre = 24000; |
|
| 402 | + break; |
|
| 403 | + case AUDIO_HAL_32K_SAMPLES: |
|
| 404 | + sample_fre = 32000; |
|
| 405 | + break; |
|
| 406 | + case AUDIO_HAL_44K_SAMPLES: |
|
| 407 | + sample_fre = 44100; |
|
| 408 | + break; |
|
| 409 | + case AUDIO_HAL_48K_SAMPLES: |
|
| 410 | + sample_fre = 48000; |
|
| 411 | + break; |
|
| 412 | + default: |
|
| 413 | + ESP_LOGE(TAG, "Unable to configure sample rate %dHz", sample_fre); |
|
| 414 | + break; |
|
| 415 | + } |
|
| 416 | + mclk_fre = sample_fre * MCLK_DIV_FRE; |
|
| 417 | + coeff = get_coeff(mclk_fre, sample_fre); |
|
| 418 | + if (coeff < 0) { |
|
| 419 | + ESP_LOGE(TAG, "Unable to configure sample rate %dHz with %dHz MCLK", sample_fre, mclk_fre); |
|
| 420 | + return ESP_FAIL; |
|
| 421 | + } |
|
| 422 | + /* |
|
| 423 | + * Set clock parammeters |
|
| 424 | + */ |
|
| 425 | + if (coeff >= 0) { |
|
| 426 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG02) & 0x07; |
|
| 427 | + regv |= (coeff_div[coeff].pre_div - 1) << 5; |
|
| 428 | + datmp = 0; |
|
| 429 | + switch (coeff_div[coeff].pre_multi) { |
|
| 430 | + case 1: |
|
| 431 | + datmp = 0; |
|
| 432 | + break; |
|
| 433 | + case 2: |
|
| 434 | + datmp = 1; |
|
| 435 | + break; |
|
| 436 | + case 4: |
|
| 437 | + datmp = 2; |
|
| 438 | + break; |
|
| 439 | + case 8: |
|
| 440 | + datmp = 3; |
|
| 441 | + break; |
|
| 442 | + default: |
|
| 443 | + break; |
|
| 444 | + } |
|
| 445 | + regv |= (datmp) << 3; |
|
| 446 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG02, regv); |
|
| 447 | + |
|
| 448 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG05) & 0x00; |
|
| 449 | + regv |= (coeff_div[coeff].adc_div - 1) << 4; |
|
| 450 | + regv |= (coeff_div[coeff].dac_div - 1) << 0; |
|
| 451 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG05, regv); |
|
| 452 | + |
|
| 453 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG03) & 0x80; |
|
| 454 | + regv |= coeff_div[coeff].fs_mode << 6; |
|
| 455 | + regv |= coeff_div[coeff].adc_osr << 0; |
|
| 456 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG03, regv); |
|
| 457 | + |
|
| 458 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG04) & 0x80; |
|
| 459 | + regv |= coeff_div[coeff].dac_osr << 0; |
|
| 460 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG04, regv); |
|
| 461 | + |
|
| 462 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG07) & 0xC0; |
|
| 463 | + regv |= coeff_div[coeff].lrck_h << 0; |
|
| 464 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG07, regv); |
|
| 465 | + |
|
| 466 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG08) & 0x00; |
|
| 467 | + regv |= coeff_div[coeff].lrck_l << 0; |
|
| 468 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG08, regv); |
|
| 469 | + |
|
| 470 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG06) & 0xE0; |
|
| 471 | + if (coeff_div[coeff].bclk_div < 19) { |
|
| 472 | + regv |= (coeff_div[coeff].bclk_div - 1) << 0; |
|
| 473 | + } else { |
|
| 474 | + regv |= (coeff_div[coeff].bclk_div) << 0; |
|
| 475 | + } |
|
| 476 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG06, regv); |
|
| 477 | + } |
|
| 478 | + |
|
| 479 | + /* |
|
| 480 | + * mclk inverted or not |
|
| 481 | + */ |
|
| 482 | + if (INVERT_MCLK) { |
|
| 483 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); |
|
| 484 | + regv |= 0x40; |
|
| 485 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); |
|
| 486 | + } else { |
|
| 487 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG01); |
|
| 488 | + regv &= ~(0x40); |
|
| 489 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG01, regv); |
|
| 490 | + } |
|
| 491 | + /* |
|
| 492 | + * sclk inverted or not |
|
| 493 | + */ |
|
| 494 | + if (INVERT_SCLK) { |
|
| 495 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG06); |
|
| 496 | + regv |= 0x20; |
|
| 497 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG06, regv); |
|
| 498 | + } else { |
|
| 499 | + regv = es8311_read_reg(ES8311_CLK_MANAGER_REG06); |
|
| 500 | + regv &= ~(0x20); |
|
| 501 | + ret |= es8311_write_reg(ES8311_CLK_MANAGER_REG06, regv); |
|
| 502 | + } |
|
| 503 | + |
|
| 504 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG13, 0x10); |
|
| 505 | + ret |= es8311_write_reg(ES8311_ADC_REG1B, 0x0A); |
|
| 506 | + ret |= es8311_write_reg(ES8311_ADC_REG1C, 0x6A); |
|
| 507 | + ret |= es8311_write_reg(ES8311_GPIO_REG44, 0x08); |
|
| 508 | + |
|
| 509 | + es8311_pa_power(true); |
|
| 510 | + return ESP_OK; |
|
| 511 | +} |
|
| 512 | + |
|
| 513 | +esp_err_t es8311_codec_deinit() |
|
| 514 | +{ |
|
| 515 | +//TODO |
|
| 516 | + return ESP_OK; |
|
| 517 | +} |
|
| 518 | + |
|
| 519 | +esp_err_t es8311_config_fmt(es_i2s_fmt_t fmt) |
|
| 520 | +{ |
|
| 521 | + esp_err_t ret = ESP_OK; |
|
| 522 | + uint8_t adc_iface = 0, dac_iface = 0; |
|
| 523 | + dac_iface = es8311_read_reg(ES8311_SDPIN_REG09); |
|
| 524 | + adc_iface = es8311_read_reg(ES8311_SDPOUT_REG0A); |
|
| 525 | + switch (fmt) { |
|
| 526 | + case AUDIO_HAL_I2S_NORMAL: |
|
| 527 | + ESP_LOGD(TAG, "ES8311 in I2S Format"); |
|
| 528 | + dac_iface &= 0xFC; |
|
| 529 | + adc_iface &= 0xFC; |
|
| 530 | + break; |
|
| 531 | + case AUDIO_HAL_I2S_LEFT: |
|
| 532 | + case AUDIO_HAL_I2S_RIGHT: |
|
| 533 | + ESP_LOGD(TAG, "ES8311 in LJ Format"); |
|
| 534 | + adc_iface &= 0xFC; |
|
| 535 | + dac_iface &= 0xFC; |
|
| 536 | + adc_iface |= 0x01; |
|
| 537 | + dac_iface |= 0x01; |
|
| 538 | + break; |
|
| 539 | + case AUDIO_HAL_I2S_DSP: |
|
| 540 | + ESP_LOGD(TAG, "ES8311 in DSP-A Format"); |
|
| 541 | + adc_iface &= 0xDC; |
|
| 542 | + dac_iface &= 0xDC; |
|
| 543 | + adc_iface |= 0x03; |
|
| 544 | + dac_iface |= 0x03; |
|
| 545 | + break; |
|
| 546 | + default: |
|
| 547 | + dac_iface &= 0xFC; |
|
| 548 | + adc_iface &= 0xFC; |
|
| 549 | + break; |
|
| 550 | + } |
|
| 551 | + ret |= es8311_write_reg(ES8311_SDPIN_REG09, dac_iface); |
|
| 552 | + ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, adc_iface); |
|
| 553 | + |
|
| 554 | + return ret; |
|
| 555 | +} |
|
| 556 | + |
|
| 557 | +esp_err_t es8311_set_bits_per_sample(audio_hal_iface_bits_t bits) |
|
| 558 | +{ |
|
| 559 | + esp_err_t ret = ESP_OK; |
|
| 560 | + uint8_t adc_iface = 0, dac_iface = 0; |
|
| 561 | + dac_iface = es8311_read_reg(ES8311_SDPIN_REG09); |
|
| 562 | + adc_iface = es8311_read_reg(ES8311_SDPOUT_REG0A); |
|
| 563 | + switch (bits) { |
|
| 564 | + case AUDIO_HAL_BIT_LENGTH_16BITS: |
|
| 565 | + dac_iface |= 0x0c; |
|
| 566 | + adc_iface |= 0x0c; |
|
| 567 | + break; |
|
| 568 | + case AUDIO_HAL_BIT_LENGTH_24BITS: |
|
| 569 | + break; |
|
| 570 | + case AUDIO_HAL_BIT_LENGTH_32BITS: |
|
| 571 | + dac_iface |= 0x10; |
|
| 572 | + adc_iface |= 0x10; |
|
| 573 | + break; |
|
| 574 | + default: |
|
| 575 | + dac_iface |= 0x0c; |
|
| 576 | + adc_iface |= 0x0c; |
|
| 577 | + break; |
|
| 578 | + |
|
| 579 | + } |
|
| 580 | + ret |= es8311_write_reg(ES8311_SDPIN_REG09, dac_iface); |
|
| 581 | + ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, adc_iface); |
|
| 582 | + |
|
| 583 | + return ret; |
|
| 584 | +} |
|
| 585 | + |
|
| 586 | +esp_err_t es8311_codec_config_i2s(audio_hal_codec_mode_t mode, audio_hal_codec_i2s_iface_t *iface) |
|
| 587 | +{ |
|
| 588 | + int ret = ESP_OK; |
|
| 589 | + ret |= es8311_set_bits_per_sample(iface->bits); |
|
| 590 | + ret |= es8311_config_fmt(iface->fmt); |
|
| 591 | + return ret; |
|
| 592 | +} |
|
| 593 | + |
|
| 594 | +esp_err_t es8311_codec_ctrl_state(audio_hal_codec_mode_t mode, audio_hal_ctrl_t ctrl_state) |
|
| 595 | +{ |
|
| 596 | + esp_err_t ret = ESP_OK; |
|
| 597 | + es_module_t es_mode = ES_MODULE_MIN; |
|
| 598 | + |
|
| 599 | + switch (mode) { |
|
| 600 | + case AUDIO_HAL_CODEC_MODE_ENCODE: |
|
| 601 | + es_mode = ES_MODULE_ADC; |
|
| 602 | + break; |
|
| 603 | + case AUDIO_HAL_CODEC_MODE_LINE_IN: |
|
| 604 | + es_mode = ES_MODULE_LINE; |
|
| 605 | + break; |
|
| 606 | + case AUDIO_HAL_CODEC_MODE_DECODE: |
|
| 607 | + es_mode = ES_MODULE_DAC; |
|
| 608 | + break; |
|
| 609 | + case AUDIO_HAL_CODEC_MODE_BOTH: |
|
| 610 | + es_mode = ES_MODULE_ADC_DAC; |
|
| 611 | + break; |
|
| 612 | + default: |
|
| 613 | + es_mode = ES_MODULE_DAC; |
|
| 614 | + ESP_LOGW(TAG, "Codec mode not support, default is decode mode"); |
|
| 615 | + break; |
|
| 616 | + } |
|
| 617 | + |
|
| 618 | + if (ctrl_state == AUDIO_HAL_CTRL_START) { |
|
| 619 | + ret |= es8311_start(es_mode); |
|
| 620 | + } else { |
|
| 621 | + ESP_LOGW(TAG, "The codec is about to stop"); |
|
| 622 | + ret |= es8311_stop(es_mode); |
|
| 623 | + } |
|
| 624 | + |
|
| 625 | + return ret; |
|
| 626 | +} |
|
| 627 | + |
|
| 628 | +esp_err_t es8311_start(es_module_t mode) |
|
| 629 | +{ |
|
| 630 | + esp_err_t ret = ESP_OK; |
|
| 631 | + uint8_t adc_iface = 0, dac_iface = 0; |
|
| 632 | + |
|
| 633 | + dac_iface = es8311_read_reg(ES8311_SDPIN_REG09) & 0xBF; |
|
| 634 | + adc_iface = es8311_read_reg(ES8311_SDPOUT_REG0A) & 0xBF; |
|
| 635 | + adc_iface |= BIT(6); |
|
| 636 | + dac_iface |= BIT(6); |
|
| 637 | + |
|
| 638 | + if (mode == ES_MODULE_LINE) { |
|
| 639 | + ESP_LOGE(TAG, "The codec es8311 doesn't support ES_MODULE_LINE mode"); |
|
| 640 | + return ESP_FAIL; |
|
| 641 | + } |
|
| 642 | + if (mode == ES_MODULE_ADC || mode == ES_MODULE_ADC_DAC) { |
|
| 643 | + adc_iface &= ~(BIT(6)); |
|
| 644 | + } |
|
| 645 | + if (mode == ES_MODULE_DAC || mode == ES_MODULE_ADC_DAC) { |
|
| 646 | + dac_iface &= ~(BIT(6)); |
|
| 647 | + } |
|
| 648 | + |
|
| 649 | + ret |= es8311_write_reg(ES8311_SDPIN_REG09, dac_iface); |
|
| 650 | + ret |= es8311_write_reg(ES8311_SDPOUT_REG0A, adc_iface); |
|
| 651 | + |
|
| 652 | + ret |= es8311_write_reg(ES8311_DAC_REG32, 0xBF); |
|
| 653 | + ret |= es8311_write_reg(ES8311_ADC_REG17, 0xBF); |
|
| 654 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG0E, 0x02); |
|
| 655 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG12, 0x00); |
|
| 656 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG14, 0x1A); |
|
| 657 | + |
|
| 658 | + /* |
|
| 659 | + * pdm dmic enable or disable |
|
| 660 | + */ |
|
| 661 | + int regv = 0; |
|
| 662 | + if (IS_DMIC) { |
|
| 663 | + regv = es8311_read_reg(ES8311_SYSTEM_REG14); |
|
| 664 | + regv |= 0x40; |
|
| 665 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG14, regv); |
|
| 666 | + } else { |
|
| 667 | + regv = es8311_read_reg(ES8311_SYSTEM_REG14); |
|
| 668 | + regv &= ~(0x40); |
|
| 669 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG14, regv); |
|
| 670 | + } |
|
| 671 | + |
|
| 672 | + ret |= es8311_write_reg(ES8311_SYSTEM_REG0D, 0x01); |
|
| 673 | + ret |= es8311_write_reg(ES8311_ADC_REG15, 0x40); |
|
| 674 | + ret |= es8311_write_reg(ES8311_DAC_REG37, 0x48); |
|
| 675 | + ret |= es8311_write_reg(ES8311_GP_REG45, 0x00); |
|
| 676 | + |
|
| 677 | + return ret; |
|
| 678 | +} |
|
| 679 | + |
|
| 680 | +esp_err_t es8311_stop(es_module_t mode) |
|
| 681 | +{ |
|
| 682 | + esp_err_t ret = ESP_OK; |
|
| 683 | + es8311_suspend(); |
|
| 684 | + return ret; |
|
| 685 | +} |
|
| 686 | + |
|
| 687 | +int es8311_codec_set_voice_volume(int volume) |
|
| 688 | +{ |
|
| 689 | + int res = 0; |
|
| 690 | + if (volume < 0) { |
|
| 691 | + volume = 0; |
|
| 692 | + } else if (volume > 100) { |
|
| 693 | + volume = 100; |
|
| 694 | + } |
|
| 695 | + int vol = (volume) * 2550 / 1000; |
|
| 696 | + ESP_LOGD(TAG, "SET: volume:%d", vol); |
|
| 697 | + es8311_write_reg(ES8311_DAC_REG32, vol); |
|
| 698 | + return res; |
|
| 699 | +} |
|
| 700 | + |
|
| 701 | +int es8311_codec_get_voice_volume(int *volume) |
|
| 702 | +{ |
|
| 703 | + int res = ESP_OK; |
|
| 704 | + int regv = 0; |
|
| 705 | + regv = es8311_read_reg(ES8311_DAC_REG32); |
|
| 706 | + if (regv == ESP_FAIL) { |
|
| 707 | + *volume = 0; |
|
| 708 | + res = ESP_FAIL; |
|
| 709 | + } else { |
|
| 710 | + *volume = regv * 100 / 256; |
|
| 711 | + } |
|
| 712 | + ESP_LOGD(TAG, "GET: res:%d, volume:%d", regv, *volume); |
|
| 713 | + return res; |
|
| 714 | +} |
|
| 715 | + |
|
| 716 | +esp_err_t es8311_set_voice_mute(bool enable) |
|
| 717 | +{ |
|
| 718 | + int res = 0; |
|
| 719 | + ESP_LOGD(TAG, "Es8311SetVoiceMute volume:%d", enable); |
|
| 720 | + es8311_mute(enable); |
|
| 721 | + return res; |
|
| 722 | +} |
|
| 723 | + |
|
| 724 | +int es8311_get_voice_mute(int *mute) |
|
| 725 | +{ |
|
| 726 | + int res = -1; |
|
| 727 | + uint8_t reg = 0; |
|
| 728 | + res = es8311_read_reg(ES8311_DAC_REG31); |
|
| 729 | + if (res != ESP_FAIL) { |
|
| 730 | + reg = (res & 0x20) >> 5; |
|
| 731 | + } |
|
| 732 | + *mute = reg; |
|
| 733 | + return res; |
|
| 734 | +} |
|
| 735 | + |
|
| 736 | +esp_err_t es8311_set_mic_gain(es8311_mic_gain_t gain_db) |
|
| 737 | +{ |
|
| 738 | + int res = 0; |
|
| 739 | + res = es8311_write_reg(ES8311_ADC_REG16, gain_db); // MIC gain scale |
|
| 740 | + return res; |
|
| 741 | +} |
|
| 742 | + |
|
| 743 | +void es8311_read_all() |
|
| 744 | +{ |
|
| 745 | + for (int i = 0; i < 0x4A; i++) { |
|
| 746 | + uint8_t reg = es8311_read_reg(i); |
|
| 747 | + ets_printf("REG:%02x, %02x\n", reg, i); |
|
| 748 | + } |
|
| 749 | +} |
Chip-cn-dat/everest-semi-dat/ES8311-dat/ES8311-SDK-dat/test/ES8311-code-spk5/es8311.h
| ... | ... | @@ -0,0 +1,237 @@ |
| 1 | +/* |
|
| 2 | + * ESPRESSIF MIT License |
|
| 3 | + * |
|
| 4 | + * Copyright (c) 2019 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD> |
|
| 5 | + * |
|
| 6 | + * Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in which case, |
|
| 7 | + * it is free of charge, to any person obtaining a copy of this software and associated |
|
| 8 | + * documentation files (the "Software"), to deal in the Software without restriction, including |
|
| 9 | + * without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, |
|
| 10 | + * and/or sell copies of the Software, and to permit persons to whom the Software is furnished |
|
| 11 | + * to do so, subject to the following conditions: |
|
| 12 | + * |
|
| 13 | + * The above copyright notice and this permission notice shall be included in all copies or |
|
| 14 | + * substantial portions of the Software. |
|
| 15 | + * |
|
| 16 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
| 17 | + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS |
|
| 18 | + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR |
|
| 19 | + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER |
|
| 20 | + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
|
| 21 | + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|
| 22 | + * |
|
| 23 | + */ |
|
| 24 | + |
|
| 25 | +#ifndef _ES8311_H |
|
| 26 | +#define _ES8311_H |
|
| 27 | + |
|
| 28 | +#include "audio_hal.h" |
|
| 29 | +#include "esp_types.h" |
|
| 30 | +#include "esxxx_common.h" |
|
| 31 | + |
|
| 32 | +/* |
|
| 33 | + * ES8311_REGISTER NAME_REG_REGISTER ADDRESS |
|
| 34 | + */ |
|
| 35 | +#define ES8311_RESET_REG00 0x00 /*reset digital,csm,clock manager etc.*/ |
|
| 36 | + |
|
| 37 | +/* |
|
| 38 | + * Clock Scheme Register definition |
|
| 39 | + */ |
|
| 40 | +#define ES8311_CLK_MANAGER_REG01 0x01 /* select clk src for mclk, enable clock for codec */ |
|
| 41 | +#define ES8311_CLK_MANAGER_REG02 0x02 /* clk divider and clk multiplier */ |
|
| 42 | +#define ES8311_CLK_MANAGER_REG03 0x03 /* adc fsmode and osr */ |
|
| 43 | +#define ES8311_CLK_MANAGER_REG04 0x04 /* dac osr */ |
|
| 44 | +#define ES8311_CLK_MANAGER_REG05 0x05 /* clk divier for adc and dac */ |
|
| 45 | +#define ES8311_CLK_MANAGER_REG06 0x06 /* bclk inverter and divider */ |
|
| 46 | +#define ES8311_CLK_MANAGER_REG07 0x07 /* tri-state, lrck divider */ |
|
| 47 | +#define ES8311_CLK_MANAGER_REG08 0x08 /* lrck divider */ |
|
| 48 | +/* |
|
| 49 | + * SDP |
|
| 50 | + */ |
|
| 51 | +#define ES8311_SDPIN_REG09 0x09 /* dac serial digital port */ |
|
| 52 | +#define ES8311_SDPOUT_REG0A 0x0A /* adc serial digital port */ |
|
| 53 | +/* |
|
| 54 | + * SYSTEM |
|
| 55 | + */ |
|
| 56 | +#define ES8311_SYSTEM_REG0B 0x0B /* system */ |
|
| 57 | +#define ES8311_SYSTEM_REG0C 0x0C /* system */ |
|
| 58 | +#define ES8311_SYSTEM_REG0D 0x0D /* system, power up/down */ |
|
| 59 | +#define ES8311_SYSTEM_REG0E 0x0E /* system, power up/down */ |
|
| 60 | +#define ES8311_SYSTEM_REG0F 0x0F /* system, low power */ |
|
| 61 | +#define ES8311_SYSTEM_REG10 0x10 /* system */ |
|
| 62 | +#define ES8311_SYSTEM_REG11 0x11 /* system */ |
|
| 63 | +#define ES8311_SYSTEM_REG12 0x12 /* system, Enable DAC */ |
|
| 64 | +#define ES8311_SYSTEM_REG13 0x13 /* system */ |
|
| 65 | +#define ES8311_SYSTEM_REG14 0x14 /* system, select DMIC, select analog pga gain */ |
|
| 66 | +/* |
|
| 67 | + * ADC |
|
| 68 | + */ |
|
| 69 | +#define ES8311_ADC_REG15 0x15 /* ADC, adc ramp rate, dmic sense */ |
|
| 70 | +#define ES8311_ADC_REG16 0x16 /* ADC */ |
|
| 71 | +#define ES8311_ADC_REG17 0x17 /* ADC, volume */ |
|
| 72 | +#define ES8311_ADC_REG18 0x18 /* ADC, alc enable and winsize */ |
|
| 73 | +#define ES8311_ADC_REG19 0x19 /* ADC, alc maxlevel */ |
|
| 74 | +#define ES8311_ADC_REG1A 0x1A /* ADC, alc automute */ |
|
| 75 | +#define ES8311_ADC_REG1B 0x1B /* ADC, alc automute, adc hpf s1 */ |
|
| 76 | +#define ES8311_ADC_REG1C 0x1C /* ADC, equalizer, hpf s2 */ |
|
| 77 | +/* |
|
| 78 | + * DAC |
|
| 79 | + */ |
|
| 80 | +#define ES8311_DAC_REG31 0x31 /* DAC, mute */ |
|
| 81 | +#define ES8311_DAC_REG32 0x32 /* DAC, volume */ |
|
| 82 | +#define ES8311_DAC_REG33 0x33 /* DAC, offset */ |
|
| 83 | +#define ES8311_DAC_REG34 0x34 /* DAC, drc enable, drc winsize */ |
|
| 84 | +#define ES8311_DAC_REG35 0x35 /* DAC, drc maxlevel, minilevel */ |
|
| 85 | +#define ES8311_DAC_REG37 0x37 /* DAC, ramprate */ |
|
| 86 | +/* |
|
| 87 | + *GPIO |
|
| 88 | + */ |
|
| 89 | +#define ES8311_GPIO_REG44 0x44 /* GPIO, dac2adc for test */ |
|
| 90 | +#define ES8311_GP_REG45 0x45 /* GP CONTROL */ |
|
| 91 | +/* |
|
| 92 | + * CHIP |
|
| 93 | + */ |
|
| 94 | +#define ES8311_CHD1_REGFD 0xFD /* CHIP ID1 */ |
|
| 95 | +#define ES8311_CHD2_REGFE 0xFE /* CHIP ID2 */ |
|
| 96 | +#define ES8311_CHVER_REGFF 0xFF /* VERSION */ |
|
| 97 | +#define ES8311_CHD1_REGFD 0xFD /* CHIP ID1 */ |
|
| 98 | + |
|
| 99 | +#define ES8311_MAX_REGISTER 0xFF |
|
| 100 | + |
|
| 101 | +typedef enum { |
|
| 102 | + ES8311_MIC_GAIN_MIN = -1, |
|
| 103 | + ES8311_MIC_GAIN_0DB, |
|
| 104 | + ES8311_MIC_GAIN_6DB, |
|
| 105 | + ES8311_MIC_GAIN_12DB, |
|
| 106 | + ES8311_MIC_GAIN_18DB, |
|
| 107 | + ES8311_MIC_GAIN_24DB, |
|
| 108 | + ES8311_MIC_GAIN_30DB, |
|
| 109 | + ES8311_MIC_GAIN_36DB, |
|
| 110 | + ES8311_MIC_GAIN_42DB, |
|
| 111 | + ES8311_MIC_GAIN_MAX |
|
| 112 | +} es8311_mic_gain_t; |
|
| 113 | + |
|
| 114 | +/* |
|
| 115 | + * @brief Initialize ES8311 codec chip |
|
| 116 | + * |
|
| 117 | + * @param codec_cfg configuration of ES8311 |
|
| 118 | + * |
|
| 119 | + * @return |
|
| 120 | + * - ESP_OK |
|
| 121 | + * - ESP_FAIL |
|
| 122 | + */ |
|
| 123 | +esp_err_t es8311_codec_init(audio_hal_codec_config_t *codec_cfg); |
|
| 124 | + |
|
| 125 | +/** |
|
| 126 | + * @brief Deinitialize ES8311 codec chip |
|
| 127 | + * |
|
| 128 | + * @return |
|
| 129 | + * - ESP_OK |
|
| 130 | + * - ESP_FAIL |
|
| 131 | + */ |
|
| 132 | +esp_err_t es8311_codec_deinit(void); |
|
| 133 | + |
|
| 134 | +/** |
|
| 135 | + * @brief Control ES8311 codec chip |
|
| 136 | + * |
|
| 137 | + * @param mode codec mode |
|
| 138 | + * @param ctrl_state start or stop decode or encode progress |
|
| 139 | + * |
|
| 140 | + * @return |
|
| 141 | + * - ESP_FAIL Parameter error |
|
| 142 | + * - ESP_OK Success |
|
| 143 | + */ |
|
| 144 | +esp_err_t es8311_codec_ctrl_state(audio_hal_codec_mode_t mode, audio_hal_ctrl_t ctrl_state); |
|
| 145 | + |
|
| 146 | +/** |
|
| 147 | + * @brief Configure ES8311 codec mode and I2S interface |
|
| 148 | + * |
|
| 149 | + * @param mode codec mode |
|
| 150 | + * @param iface I2S config |
|
| 151 | + * |
|
| 152 | + * @return |
|
| 153 | + * - ESP_FAIL Parameter error |
|
| 154 | + * - ESP_OK Success |
|
| 155 | + */ |
|
| 156 | +esp_err_t es8311_codec_config_i2s(audio_hal_codec_mode_t mode, audio_hal_codec_i2s_iface_t *iface); |
|
| 157 | + |
|
| 158 | +/** |
|
| 159 | + * @brief Configure ES8311 DAC mute or not. Basically you can use this function to mute the output or unmute |
|
| 160 | + * |
|
| 161 | + * @param enable enable(1) or disable(0) |
|
| 162 | + * |
|
| 163 | + * @return |
|
| 164 | + * - ESP_FAIL Parameter error |
|
| 165 | + * - ESP_OK Success |
|
| 166 | + */ |
|
| 167 | +esp_err_t es8311_set_voice_mute(bool enable); |
|
| 168 | + |
|
| 169 | +/** |
|
| 170 | + * @brief Set voice volume |
|
| 171 | + * |
|
| 172 | + * @param volume: voice volume (0~100) |
|
| 173 | + * |
|
| 174 | + * @return |
|
| 175 | + * - ESP_OK |
|
| 176 | + * - ESP_FAIL |
|
| 177 | + */ |
|
| 178 | +esp_err_t es8311_codec_set_voice_volume(int volume); |
|
| 179 | + |
|
| 180 | +/** |
|
| 181 | + * @brief Get voice volume |
|
| 182 | + * |
|
| 183 | + * @param[out] *volume: voice volume (0~100) |
|
| 184 | + * |
|
| 185 | + * @return |
|
| 186 | + * - ESP_OK |
|
| 187 | + * - ESP_FAIL |
|
| 188 | + */ |
|
| 189 | +esp_err_t es8311_codec_get_voice_volume(int *volume); |
|
| 190 | + |
|
| 191 | +/** |
|
| 192 | + * @brief Configure ES8311 I2S format |
|
| 193 | + * |
|
| 194 | + * @param mod: set ADC or DAC or both |
|
| 195 | + * @param cfg: ES8388 I2S format |
|
| 196 | + * |
|
| 197 | + * @return |
|
| 198 | + * - ESP_OK |
|
| 199 | + * - ESP_FAIL |
|
| 200 | + */ |
|
| 201 | +esp_err_t es8311_config_fmt(es_i2s_fmt_t fmt); |
|
| 202 | + |
|
| 203 | +/** |
|
| 204 | + * @brief Configure ES8311 data sample bits |
|
| 205 | + * |
|
| 206 | + * @param mode: set ADC or DAC or both |
|
| 207 | + * @param bit_per_sample: bit number of per sample |
|
| 208 | + * |
|
| 209 | + * @return |
|
| 210 | + * - ESP_OK |
|
| 211 | + * - ESP_FAIL |
|
| 212 | + */ |
|
| 213 | +esp_err_t es8311_set_bits_per_sample(audio_hal_iface_bits_t bits); |
|
| 214 | + |
|
| 215 | +/** |
|
| 216 | + * @brief Start ES8311 codec chip |
|
| 217 | + * |
|
| 218 | + * @param mode: set ADC or DAC or both |
|
| 219 | + * |
|
| 220 | + * @return |
|
| 221 | + * - ESP_OK |
|
| 222 | + * - ESP_FAIL |
|
| 223 | + */ |
|
| 224 | +esp_err_t es8311_start(es_module_t mode); |
|
| 225 | + |
|
| 226 | +/** |
|
| 227 | + * @brief Stop ES8311 codec chip |
|
| 228 | + * |
|
| 229 | + * @param mode: set ADC or DAC or both |
|
| 230 | + * |
|
| 231 | + * @return |
|
| 232 | + * - ESP_OK |
|
| 233 | + * - ESP_FAIL |
|
| 234 | + */ |
|
| 235 | +esp_err_t es8311_stop(es_module_t mode); |
|
| 236 | + |
|
| 237 | +#endif |
Tech-dat/Interface-dat/I2S-dat/I2S-dat.md
| ... | ... | @@ -24,6 +24,8 @@ |
| 24 | 24 | |
| 25 | 25 | - [[sensor-microphone-dat]] - [[sensor-microphone-I2S-dat]]
|
| 26 | 26 | |
| 27 | +- [[I2S-speaker-microphone-dat]] - [[ES8311-dat]]
|
|
| 28 | +
|
|
| 27 | 29 | ## info
|
| 28 | 30 | |
| 29 | 31 | An I2S (Interactive Two-Way Serial) interface is a type of serial communication protocol used for transferring data between devices.
|
Tech-dat/Interface-dat/I2S-dat/I2S-speaker-microphone-dat/I2S-speaker-microphone-dat.md
| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | + |
|
| 2 | + |
|
| 3 | +# I2S-speaker-microphone-dat |
|
| 4 | + |
|
| 5 | +- [[I2S-speaker-microphone-dat]] - [[ES8311-dat]] - [[ES8311-SDK-dat]] |
|
| 6 | + |
|
| 7 | + |
|
| 8 | + |
|
| 9 | + |
|
| 10 | +## ref |
|
| 11 | + |
Tech-dat/acturator-dat/speaker-dat/speaker-I2S-dat/I2S-speaker-general-1/I2S-speaker-general-1.ino
| ... | ... | @@ -0,0 +1,126 @@ |
| 1 | +/** |
|
| 2 | + * HT517-test-1.ino |
|
| 3 | + * |
|
| 4 | + * Simple I2S audio output demo for ESP32-S3 → I2S amplifier (MAX98357 / PCM5102 / etc.) |
|
| 5 | + * |
|
| 6 | + * Hardware connection (ESP32-S3 → I2S amplifier): |
|
| 7 | + * I2S_BCK (Bit Clock) → GPIO 4 -> BCK / BCLK / SCK |
|
| 8 | + * I2S_WS (Word Select) → GPIO 5 -> WS / LRCK / FS |
|
| 9 | + * I2S_DATA (Data) → GPIO 6 -> DIN / DATA / SD |
|
| 10 | + * (Optional) I2S_MCLK (Master Clock) → GPIO 7 -> MCLK (not required by MAX98357) |
|
| 11 | + * |
|
| 12 | + * Tested amplifiers: MAX98357, PCM5102, I2S DAC, etc. |
|
| 13 | + * Output: 16-bit 44100 Hz mono sine wave (left+right same data). |
|
| 14 | + */ |
|
| 15 | + |
|
| 16 | +#include <driver/i2s.h> |
|
| 17 | +#include <math.h> |
|
| 18 | + |
|
| 19 | +// ============ CONFIGURATION ============ |
|
| 20 | +#define SAMPLE_RATE 44100 |
|
| 21 | +#define BITS_PER_SAMPLE 16 |
|
| 22 | +#define I2S_PORT I2S_NUM_0 |
|
| 23 | + |
|
| 24 | +// GPIO pins (adjust to your wiring) |
|
| 25 | +#define I2S_BCK 4 // Bit Clock |
|
| 26 | +#define I2S_WS 5 // Word Select (LRCK) |
|
| 27 | +#define I2S_DATA 6 // Data out (DIN) |
|
| 28 | +#define I2S_MCLK -1 // -1 = disable Master Clock (not needed for MAX98357) |
|
| 29 | + |
|
| 30 | +// ============ BUFFER ============ |
|
| 31 | +#define BUF_LEN 256 // samples per channel per buffer |
|
| 32 | +int16_t buf[BUF_LEN * 2]; // stereo interleaved |
|
| 33 | + |
|
| 34 | +// ============ I2S CONFIG ============ |
|
| 35 | + |
|
| 36 | +void setupI2S() { |
|
| 37 | + i2s_config_t i2s_config = { |
|
| 38 | + .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX), |
|
| 39 | + .sample_rate = SAMPLE_RATE, |
|
| 40 | + .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, |
|
| 41 | + .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, |
|
| 42 | + .communication_format = I2S_COMM_FORMAT_STAND_I2S, |
|
| 43 | + .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, |
|
| 44 | + .dma_buf_count = 8, |
|
| 45 | + .dma_buf_len = BUF_LEN, |
|
| 46 | + .use_apll = true, |
|
| 47 | + .tx_desc_auto_clear = true, |
|
| 48 | + .fixed_mclk = 0, |
|
| 49 | + }; |
|
| 50 | + |
|
| 51 | + i2s_pin_config_t pin_config = { |
|
| 52 | + .bck_io_num = I2S_BCK, |
|
| 53 | + .ws_io_num = I2S_WS, |
|
| 54 | + .data_out_num = I2S_DATA, |
|
| 55 | + .data_in_num = I2S_PIN_NO_CHANGE, |
|
| 56 | + }; |
|
| 57 | + |
|
| 58 | + // Install and start I2S driver |
|
| 59 | + esp_err_t err = i2s_driver_install(I2S_PORT, &i2s_config, 0, NULL); |
|
| 60 | + if (err != ESP_OK) { |
|
| 61 | + Serial.printf("FAIL: i2s_driver_install returned %d\n", err); |
|
| 62 | + while (1) delay(100); |
|
| 63 | + } |
|
| 64 | + |
|
| 65 | + // Set pins (only if MCLK is not used) |
|
| 66 | + err = i2s_set_pin(I2S_PORT, &pin_config); |
|
| 67 | + if (err != ESP_OK) { |
|
| 68 | + Serial.printf("FAIL: i2s_set_pin returned %d\n", err); |
|
| 69 | + while (1) delay(100); |
|
| 70 | + } |
|
| 71 | + |
|
| 72 | + // Set MCLK if enabled |
|
| 73 | + if (I2S_MCLK > 0) { |
|
| 74 | + i2s_set_clk(I2S_PORT, SAMPLE_RATE, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_STEREO); |
|
| 75 | + } |
|
| 76 | + |
|
| 77 | + Serial.println("I2S initialized OK"); |
|
| 78 | +} |
|
| 79 | + |
|
| 80 | +// ============ GENERATE AUDIO ============ |
|
| 81 | +void generateSine(int16_t *buf, int len, float freq, float amplitude, uint32_t &phase_acc) { |
|
| 82 | + float phase_step = freq / SAMPLE_RATE; // fractional phase increment per sample |
|
| 83 | + for (int i = 0; i < len; i++) { |
|
| 84 | + float phase = (phase_acc & 0xFFFF) / 65536.0f; // 0.0 ~ 1.0 |
|
| 85 | + int16_t sample = (int16_t)(amplitude * sinf(phase * 2.0f * M_PI)); |
|
| 86 | + // stereo: left = right |
|
| 87 | + buf[i * 2 + 0] = sample; // left |
|
| 88 | + buf[i * 2 + 1] = sample; // right |
|
| 89 | + phase_acc = (uint32_t)(phase_acc + phase_step * 65536); |
|
| 90 | + } |
|
| 91 | +} |
|
| 92 | + |
|
| 93 | +// ============ SETUP ============ |
|
| 94 | +void setup() { |
|
| 95 | + Serial.begin(115200); |
|
| 96 | + delay(500); |
|
| 97 | + Serial.println("\n--- I2S Audio Demo for ESP32-S3 ---"); |
|
| 98 | + |
|
| 99 | + setupI2S(); |
|
| 100 | +} |
|
| 101 | + |
|
| 102 | +// ============ LOOP ============ |
|
| 103 | +void loop() { |
|
| 104 | + static uint32_t phase_acc = 0; |
|
| 105 | + static float freq = 440.0f; // A4 note |
|
| 106 | + static float amplitude = 16000; // 0 ~ 32767 |
|
| 107 | + |
|
| 108 | + generateSine(buf, BUF_LEN, freq, amplitude, phase_acc); |
|
| 109 | + |
|
| 110 | + size_t bytes_written = 0; |
|
| 111 | + esp_err_t err = i2s_write(I2S_PORT, buf, sizeof(buf), &bytes_written, portMAX_DELAY); |
|
| 112 | + if (err != ESP_OK) { |
|
| 113 | + Serial.printf("I2S write error: %d\n", err); |
|
| 114 | + } |
|
| 115 | + |
|
| 116 | + // Optional: cycle through notes every 2 seconds |
|
| 117 | + static unsigned long last_note_change = 0; |
|
| 118 | + if (millis() - last_note_change > 2000) { |
|
| 119 | + last_note_change = millis(); |
|
| 120 | + static float notes[] = {262, 294, 330, 349, 392, 440, 494, 523}; // C4 ~ C5 |
|
| 121 | + static int note_idx = 0; |
|
| 122 | + freq = notes[note_idx]; |
|
| 123 | + note_idx = (note_idx + 1) % 8; |
|
| 124 | + Serial.printf("Playing: %.0f Hz\n", freq); |
|
| 125 | + } |
|
| 126 | +} |
Tech-dat/acturator-dat/speaker-dat/speaker-I2S-dat/speaker-I2S-dat.md
| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | - |
|
| 2 | 1 | # speaker-I2S-dat |
| 3 | 2 | |
| 4 | -- [[speaker-dat]] - [[speaker-I2S-dat]] |
|
| 3 | +- [[speaker-dat]] - [[speaker-I2S-dat]] - [[I2S-dat]] |
|
| 5 | 4 | |
| 6 | 5 | - [[amplifier-dat]] |
| 7 | 6 | |
| ... | ... | @@ -24,7 +23,7 @@ I2S DAC Decoder speaker |
| 24 | 23 | |
| 25 | 24 | - [[UDA1334-dat]] - [[AMP1013-dat]] - [[NXP-dat]] |
| 26 | 25 | |
| 27 | -- [[HT517-dat]] |
|
| 26 | +- [[HT517-dat]] - [[heroic-dat]] - [[speaker-I2S-dat]] |
|
| 28 | 27 | |
| 29 | 28 | |
| 30 | 29 | ## Common Microphone, Speaker Wiring |
| ... | ... | @@ -62,4 +61,84 @@ I2S Circuit: |
| 62 | 61 | - ESP32-S2 has DAC on GPIO pins 17 and 18. |
| 63 | 62 | - Connect speaker(s) or headphones. |
| 64 | 63 | |
| 65 | -- [[MAX98357-dat]] |
|
| ... | ... | \ No newline at end of file |
| 0 | +- [[MAX98357-dat]] |
|
| 1 | + |
|
| 2 | + |
|
| 3 | +## general test code |
|
| 4 | + |
|
| 5 | +- [[I2S-speaker-general-1.ino]] |
|
| 6 | + |
|
| 7 | +### I2S Demo Code for ESP32-S3 (I2S-speaker-general-1.ino) |
|
| 8 | + |
|
| 9 | +Simple I2S audio output demo for ESP32-S3 → I2S amplifier (MAX98357 / PCM5102 / etc.). |
|
| 10 | + |
|
| 11 | +#### Pinout (ESP32-S3 → I2S Amplifier) |
|
| 12 | + |
|
| 13 | +| Signal | GPIO | Amplifier Pin | |
|
| 14 | +| -------------------- | ------------------------- | ---------------- | |
|
| 15 | +| I2S_BCK (Bit Clock) | GPIO 4 | BCK / BCLK / SCK | |
|
| 16 | +| I2S_WS (Word Select) | GPIO 5 | WS / LRCK / FS | |
|
| 17 | +| I2S_DATA | GPIO 6 | DIN / DATA / SD | |
|
| 18 | +| I2S_MCLK (Optional) | GPIO 7 (or -1 to disable) | MCLK | |
|
| 19 | + |
|
| 20 | +#### Features |
|
| 21 | + |
|
| 22 | +| Parameter | Value | |
|
| 23 | +| ------------- | -------------------------------------------------------- | |
|
| 24 | +| Protocol | Standard Philips I2S | |
|
| 25 | +| Sample Rate | 44100 Hz | |
|
| 26 | +| Bit Depth | 16-bit | |
|
| 27 | +| Channels | Stereo (left = right) | |
|
| 28 | +| Audio Source | Sine wave generator (no external file needed) | |
|
| 29 | +| Note Sequence | C4 → D4 → E4 → F4 → G4 → A4 → B4 → C5, changing every 2s | |
|
| 30 | + |
|
| 31 | +#### Code Structure |
|
| 32 | + |
|
| 33 | +| Function | Description | |
|
| 34 | +| ---------------- | ------------------------------------------------------- | |
|
| 35 | +| `setupI2S()` | Initializes I2S driver with DMA, configures pins | |
|
| 36 | +| `generateSine()` | Fills buffer with sine wave samples at given frequency | |
|
| 37 | +| `setup()` | Serial init + I2S setup | |
|
| 38 | +| `loop()` | Generates audio and writes to I2S, cycles through notes | |
|
| 39 | + |
|
| 40 | +#### Configuration Macros |
|
| 41 | + |
|
| 42 | +| Macro | Default | Description | |
|
| 43 | +| ----------------- | ----------- | ---------------------------------- | |
|
| 44 | +| `SAMPLE_RATE` | 44100 | Audio sample rate in Hz | |
|
| 45 | +| `BITS_PER_SAMPLE` | 16 | Audio bit depth | |
|
| 46 | +| `I2S_PORT` | `I2S_NUM_0` | I2S controller number | |
|
| 47 | +| `I2S_BCK` | 4 | Bit Clock GPIO | |
|
| 48 | +| `I2S_WS` | 5 | Word Select GPIO | |
|
| 49 | +| `I2S_DATA` | 6 | Data out GPIO | |
|
| 50 | +| `I2S_MCLK` | -1 | Master Clock GPIO (-1 = disabled) | |
|
| 51 | +| `BUF_LEN` | 256 | Samples per channel per DMA buffer | |
|
| 52 | + |
|
| 53 | +#### Compatible Amplifiers |
|
| 54 | + |
|
| 55 | +- [[MAX98357-dat]] - no MCLK required |
|
| 56 | +- [[PCM5102-dat]] |
|
| 57 | +- [[NS4168-dat]] |
|
| 58 | +- [[UDA1334-dat]] |
|
| 59 | +- Any I2S DAC with standard Philips I2S input |
|
| 60 | + |
|
| 61 | +#### Usage |
|
| 62 | + |
|
| 63 | +1. Wire ESP32-S3 to amplifier per pinout table above |
|
| 64 | +2. Upload `I2S-speaker-general-1.ino` to ESP32-S3 (select board: ESP32S3 Dev Module) |
|
| 65 | +3. Open Serial Monitor at **115200 baud** to see note change logs |
|
| 66 | +4. Connect speaker to amplifier output — you should hear a repeating scale |
|
| 67 | + |
|
| 68 | +#### Customization |
|
| 69 | + |
|
| 70 | +- Change pins by editing `I2S_BCK`, `I2S_WS`, `I2S_DATA` macros |
|
| 71 | +- Enable MCLK by setting `I2S_MCLK` to a GPIO number (required by some DACs) |
|
| 72 | +- Adjust sample rate / bit depth via `SAMPLE_RATE` / `BITS_PER_SAMPLE` |
|
| 73 | +- Replace sine wave with WAV data by filling buffer directly |
|
| 74 | + |
|
| 75 | + |
|
| 76 | + |
|
| 77 | + |
|
| 78 | + |
|
| 79 | + |
|
| 80 | +## ref |
|
| ... | ... | \ No newline at end of file |
Tech-dat/tech-dat.md
| ... | ... | @@ -216,6 +216,8 @@ |
| 216 | 216 | |
| 217 | 217 | - [[codec-audio-dat]] - [[codec-dat]] - [[audio-dat]] - [[I2S-dat]] - [[arduino-audio-dat]] - [[media-dat]] - [[MP3-dat]] |
| 218 | 218 | |
| 219 | +- [[I2S-dat]] - [[speaker-I2S-dat]] - [[sensor-microphone-I2S-dat]] |
|
| 220 | + |
|
| 219 | 221 | - [[filter-dat]] |
| 220 | 222 | |
| 221 | 223 | - [[transmitter-current-dat]] |