Merge branch 'master' into fix_20ms_chunk_size_bug
# Conflicts: # .project # components/audio_board/CMakeLists.txt # components/audio_board/Kconfig.projbuild # components/audio_board/component.mk # components/audio_board/esp32_s2_kaluga_1_v1_2/board.c # components/audio_board/esp32_s2_kaluga_1_v1_2/board.h # components/audio_hal/driver/es8388/es8388.c # components/audio_hal/driver/es8388/headphone_detect.c # components/audio_hal/driver/tas5805m/tas5805m.c # components/custom_board/Kconfig.projbuild # components/esp_peripherals/driver/i2c_bus/i2c_bus.c # components/esp_peripherals/esp_peripherals.c # components/esp_peripherals/periph_button.c # components/esp_peripherals/periph_console.c # components/esp_peripherals/periph_led.c # components/esp_peripherals/periph_sdcard.c # components/esp_peripherals/periph_wifi.c # components/esp_peripherals/periph_ws2812.c # components/esp_peripherals/test/esp_peripherals_test.c # components/eth_interface/CMakeLists.txt # components/eth_interface/eth_interface.c # components/lightsnapcast/include/snapcast.h # components/lightsnapcast/player.c # components/wifi_interface/CMakeLists.txt # components/wifi_interface/wifi_interface.c # dependencies.lock # main/CMakeLists.txt # main/main.c # sdkconfig_PCM5102A # sdkconfig_TAS5805M Signed-off-by: Karl Osterseher <karli_o@gmx.at>
This commit is contained in:
@@ -9,10 +9,9 @@
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.pathentry">
|
||||
<pathentry kind="src" path=""/>
|
||||
<pathentry excluding="**/CMakeFiles/**" kind="out" path="build"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.pathentry">
|
||||
<pathentry excluding="**/CMakeFiles/**" kind="out" path="build"/>
|
||||
</storageModule>
|
||||
</cproject>
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -7,3 +7,6 @@
|
||||
[submodule "components/opus/opus"]
|
||||
path = components/opus/opus
|
||||
url = https://github.com/xiph/opus
|
||||
[submodule "components/improv_wifi/Improv-WiFi-Library"]
|
||||
path = components/improv_wifi/Improv-WiFi-Library
|
||||
url = https://github.com/jnthas/Improv-WiFi-Library.git
|
||||
|
||||
70
README.md
70
README.md
@@ -21,24 +21,21 @@ Please check out the task list and feel free to fill in.
|
||||
|
||||
I dropped the usage of ADF completely but copied stripped down, needed components to this project (using <b>ESP-ADF v2.6</b>).
|
||||
This was necessary because ADF was using flac in closed source precompiled library
|
||||
which made it impossible to get good results for multiroom syncing. IDF's I2S driver was also copied
|
||||
to project's components and adapted. Originally it wasn't possible to pre load DMA buffers with audio
|
||||
samples and therefore no precise sync could be achieved.
|
||||
which made it impossible to get good results for multiroom syncing.
|
||||
|
||||
### Codebase
|
||||
|
||||
The codebase is split into components and build on <b>ESP-IDF v4.3.5</b>. I still
|
||||
The codebase is split into components and build on <b>ESP-IDF v5.1.1</b>. I still
|
||||
have some refactoring on the todo list as the concept has started to settle and
|
||||
allow for new features can be added in a structured manner. In the code you
|
||||
will find parts that are only partly related features and still not on the task
|
||||
list. Also there is a lot of code clean up needed.
|
||||
|
||||
Components
|
||||
- audio-board : taken from ADF, stripped down to strictly necessary parts for usage with Lyrat v4.3
|
||||
- audio-hal : taken from ADF, stripped down to strictly necessary parts for usage with Lyrat v4.3
|
||||
- audio-sal : taken from ADF, stripped down to strictly necessary parts for usage with Lyrat v4.3
|
||||
- custom_board :
|
||||
- custom-driver : modified I2S driver from IDF v4.3.1 which supports preloading DMA buffers with valid data
|
||||
- audio-board : taken from ADF, stripped down to strictly necessary parts for playback
|
||||
- audio-hal : taken from ADF, stripped down to strictly necessary parts for playback
|
||||
- audio-sal : taken from ADF, stripped down to strictly necessary parts for playback
|
||||
- custom_board : generic board component to support easy integration of DACs
|
||||
- dsp_processor : Audio Processor, low pass filters, effects, etc.
|
||||
- esp-dsp : Submodule to the ESP-ADF done by David Douard
|
||||
- esp-peripherals : taken from ADF, stripped down to strictly necessary parts for usage with Lyrat v4.3
|
||||
@@ -121,12 +118,30 @@ git submodule update --init
|
||||
```
|
||||
|
||||
### ESP-IDF environnement configuration
|
||||
- <b>If you're on Windows :</b> Install ESP-IDF v4.3.5 locally [https://github.com/espressif/esp-idf/releases/tag/v4.3.5](https://github.com/espressif/esp-idf/releases/tag/v4.3.5). More info: [https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup-update.html](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup-update.html)
|
||||
- <b>If you're on Linux :</b> Use the docker image for ESP-IDF by following [docker build](doc/docker_build.md) doc.
|
||||
- <b>If you're on Windows :</b> Install [ESP-IDF v5.1.1](https://github.com/espressif/esp-idf/releases/tag/v5.1.1) locally ([More info](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/windows-setup-update.html)).
|
||||
- <b>If you're on Linux (docker) :</b> Use the image for ESP-IDF by following [docker build](doc/docker_build.md) doc
|
||||
- <b>If you're on Linux :</b> follow [official Espressif](https://docs.espressif.com/projects/esp-idf/en/stable/esp32/get-started/linux-macos-setup.html) instructions
|
||||
For debian based systems you'll need to do the following:
|
||||
```
|
||||
sudo apt-get install git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
|
||||
mkdir -p ~/esp
|
||||
cd ~/esp
|
||||
git clone -b v5.1.1 --recursive https://github.com/espressif/esp-idf.git
|
||||
cd ~/esp/esp-idf
|
||||
./install.sh esp32
|
||||
. ./export.sh
|
||||
```
|
||||
|
||||
<a name="config"></a>
|
||||
### Snapcast ESP Configuration
|
||||
Configure your platform:
|
||||
Frist copy one of the template sdkconfig files and rename it to sdkconfig
|
||||
|
||||
```
|
||||
cp sdkconfig_lyrat_v4.3 sdkconfig
|
||||
```
|
||||
|
||||
then configure your platform:
|
||||
|
||||
```
|
||||
idf.py menuconfig
|
||||
```
|
||||
@@ -169,6 +184,13 @@ Configure to match your setup
|
||||
```
|
||||
idf.py build flash monitor
|
||||
```
|
||||
|
||||
### Merge bin to flash at 0x0 with web.esphome.io
|
||||
|
||||
```
|
||||
esptool.py --chip esp32 merge_bin -o merged.bin --flash_size 4MB --flash_freq 80m 0x1000 build/bootloader/bootloader.bin 0x8000 build/partition_table/partition-table.bin 0xd000 build/ota_data_initial.bin 0x10000 build/snapclient.bin 0x370000 build/storage.bin
|
||||
```
|
||||
|
||||
## Test
|
||||
Setup a snapcast server on your network
|
||||
|
||||
@@ -209,29 +231,13 @@ Then on every `git commit`, a few sanity/formatting checks will be performed.
|
||||
|
||||
|
||||
## Task list
|
||||
- [ok] Fix to alinge with above
|
||||
- [ok] put kconfig to better locations in tree
|
||||
* add codec description
|
||||
- [ok] Integrate ESP wifi provision
|
||||
- [ok] Find and connect to Avahi broadcasted Snapcast server name
|
||||
- [ ] Add a client command interface layer like volume/mute control
|
||||
- [ ] put kconfig to better locations in tree
|
||||
- [ ] add missing codec's (ogg)
|
||||
- [ok] test esp-dsp functionality after ADF drop
|
||||
- [ok] Check compatibility with different HW than Lyrat v4.3
|
||||
- [ok] rework dsp_processor and test. At the moment only dspfStereo and dspfBassBoost will work. Also ensure/test we got enough RAM on WROVER modules
|
||||
- [ ] reduce dsp_processor memory footprint
|
||||
- [ ] dsp_processor: add equalizer
|
||||
* Control interface for equalizer
|
||||
- [ ] Control interface for equalizer (component: ui_http_server)
|
||||
- [ ] clean and polish code (remove all unused variables etc.)
|
||||
- [ok] Improve Documentation, e.g. Hardware guide (supported codecs)
|
||||
- [ ] upgrade to IDF v5
|
||||
- [ ] in IDF v5 use native i2s driver, as it supports preloading DMA buffer with valid data now
|
||||
- [ ] Improve Documentation
|
||||
- [ ] Throw out ADF copied components from project tree and use CmakeLists.txt to pull in necessary files from ADF
|
||||
|
||||
## Minor task
|
||||
- [ok] soft mute - play sample in buffer with decreasing volume
|
||||
- [ok] hard mute - using ADF's HAL
|
||||
- [ok] Startup: do not start parsing on samples to codec before sample ring buffer hits requested buffer size.
|
||||
- [ok] Start from empty buffer
|
||||
- [ ] fill in missing component descriptions in Readme.md
|
||||
- [ok] DAC latency setting from android app
|
||||
- [ ] fill in missing component descriptions in Readme.md
|
||||
|
||||
@@ -22,6 +22,15 @@ set(COMPONENT_SRCS
|
||||
)
|
||||
endif()
|
||||
|
||||
if (CONFIG_ESP_AI_THINKER_ES8388_BOARD)
|
||||
message(STATUS "Current board name is " CONFIG_ESP_AI_THINKER_ES8388_BOARD)
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS ./ai_thinker_es8388)
|
||||
set(COMPONENT_SRCS
|
||||
./ai_thinker_es8388/board.c
|
||||
./ai_thinker_es8388/board_pins_config.c
|
||||
)
|
||||
endif()
|
||||
|
||||
if (CONFIG_ESP_LYRAT_MINI_V1_1_BOARD)
|
||||
message(STATUS "Current board name is " CONFIG_ESP_LYRAT_MINI_V1_1_BOARD)
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS ./lyrat_mini_v1_1)
|
||||
@@ -60,7 +69,6 @@ set(COMPONENT_SRCS
|
||||
)
|
||||
endif()
|
||||
|
||||
#[[
|
||||
if (CONFIG_ESP32_S2_KALUGA_1_V1_2_BOARD)
|
||||
message(STATUS "Current board name is " CONFIG_ESP32_S2_KALUGA_1_V1_2_BOARD)
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_s2_kaluga_1_v1_2)
|
||||
@@ -70,6 +78,7 @@ set(COMPONENT_SRCS
|
||||
)
|
||||
endif()
|
||||
|
||||
#[[
|
||||
if (CONFIG_ESP32_S3_KORVO2_V3_BOARD)
|
||||
message(STATUS "Current board name is " CONFIG_ESP32_S3_KORVO2_V3_BOARD)
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS ./esp32_s3_korvo2_v3)
|
||||
|
||||
@@ -1,64 +1,330 @@
|
||||
menu "Audio HAL"
|
||||
menu "Audio Board"
|
||||
|
||||
choice AUDIO_BOARD
|
||||
prompt "Audio board"
|
||||
default ESP_LYRAT_V4_3_BOARD
|
||||
help
|
||||
Select an audio board to use with the ESP-ADF
|
||||
config AUDIO_BOARD_CUSTOM
|
||||
bool "Custom audio board"
|
||||
config ESP_LYRAT_V4_3_BOARD
|
||||
bool "ESP32-Lyrat V4.3"
|
||||
config ESP_LYRAT_V4_2_BOARD
|
||||
bool "ESP32-Lyrat V4.2"
|
||||
config ESP_LYRATD_MSC_V2_1_BOARD
|
||||
bool "ESP32-LyraTD-MSC V2.1"
|
||||
config ESP_LYRATD_MSC_V2_2_BOARD
|
||||
bool "ESP32-LyraTD-MSC V2.2"
|
||||
config ESP_LYRAT_MINI_V1_1_BOARD
|
||||
bool "ESP32-Lyrat-Mini V1.1"
|
||||
config ESP32_KORVO_DU1906_BOARD
|
||||
bool "ESP32_KORVO_DU1906"
|
||||
#config ESP32_S2_KALUGA_1_V1_2_BOARD
|
||||
# bool "ESP32-S2-Kaluga-1 v1.2"
|
||||
#config ESP32_S3_KORVO2_V3_BOARD
|
||||
# bool "ESP32-S3-Korvo-2 v3"
|
||||
#config ESP32_S3_KORVO2L_V1_BOARD
|
||||
# bool "ESP32-S3-Korvo-2L v1"
|
||||
#config ESP32_S3_BOX_LITE_BOARD
|
||||
# bool "ESP32-S3-BOX-Lite"
|
||||
#config ESP32_S3_BOX_BOARD
|
||||
# bool "ESP32-S3-BOX"
|
||||
#config ESP32_C3_LYRA_V2_BOARD
|
||||
# bool "ESP32-C3-Lyra-v2.0"
|
||||
#config ESP32_C6_DEVKIT_BOARD
|
||||
# bool "ESP32-C6-DEVKIT"
|
||||
config I2S_USE_MSB_FORMAT
|
||||
bool
|
||||
default n
|
||||
help
|
||||
Specifies if the I2S should use MSB format instead. Some DACs (such as PT8211) need this enabled to ensure
|
||||
compatibility with their LSBJ timing under their native bit-depth. This option is only adjusted by the DAC
|
||||
choice and is not exposed to menuconfig.
|
||||
See https://github.com/schreibfaul1/ESP32-audioI2S/blob/1d9b299d0197f99fc70335295adcd226dc220f88/src/Audio.cpp#L4929
|
||||
|
||||
endchoice
|
||||
choice AUDIO_BOARD
|
||||
prompt "Audio board"
|
||||
default ESP_LYRAT_V4_3_BOARD
|
||||
help
|
||||
Select an audio board to use with the ESP-ADF
|
||||
config AUDIO_BOARD_CUSTOM
|
||||
bool "Custom audio board"
|
||||
config ESP_LYRAT_V4_3_BOARD
|
||||
bool "ESP32-Lyrat V4.3"
|
||||
config ESP_LYRAT_V4_2_BOARD
|
||||
bool "ESP32-Lyrat V4.2"
|
||||
config ESP_LYRATD_MSC_V2_1_BOARD
|
||||
bool "ESP32-LyraTD-MSC V2.1"
|
||||
config ESP_LYRATD_MSC_V2_2_BOARD
|
||||
bool "ESP32-LyraTD-MSC V2.2"
|
||||
config ESP_LYRAT_MINI_V1_1_BOARD
|
||||
bool "ESP32-Lyrat-Mini V1.1"
|
||||
config ESP32_KORVO_DU1906_BOARD
|
||||
bool "ESP32_KORVO_DU1906"
|
||||
config ESP32_S2_KALUGA_1_V1_2_BOARD
|
||||
bool "ESP32-S2-Kaluga-1 v1.2"
|
||||
config ESP_AI_THINKER_ES8388_BOARD
|
||||
bool "ESP-AI-Thinker-ES8388 v2.2"
|
||||
#config ESP32_S3_KORVO2_V3_BOARD
|
||||
# bool "ESP32-S3-Korvo-2 v3"
|
||||
#config ESP32_S3_KORVO2L_V1_BOARD
|
||||
# bool "ESP32-S3-Korvo-2L v1"
|
||||
#config ESP32_S3_BOX_LITE_BOARD
|
||||
# bool "ESP32-S3-BOX-Lite"
|
||||
#config ESP32_S3_BOX_BOARD
|
||||
# bool "ESP32-S3-BOX"
|
||||
#config ESP32_C3_LYRA_V2_BOARD
|
||||
# bool "ESP32-C3-Lyra-v2.0"
|
||||
#config ESP32_C6_DEVKIT_BOARD
|
||||
# bool "ESP32-C6-DEVKIT"
|
||||
|
||||
choice ESP32_KORVO_DU1906_DAC
|
||||
prompt "ESP32 KORVO DU1906 Board DAC chip"
|
||||
depends on ESP32_KORVO_DU1906_BOARD
|
||||
default ESP32_KORVO_DU1906_DAC_TAS5805M
|
||||
help
|
||||
Select DAC chip to use on ESP32_KORVO_DU1906 board
|
||||
endchoice
|
||||
|
||||
config ESP32_KORVO_DU1906_DAC_TAS5805M
|
||||
bool "ESP32_KORVO_DU1906_DAC_TAS5805M"
|
||||
config ESP32_KORVO_DU1906_DAC_ES7148
|
||||
bool "ESP32_KORVO_DU1906_DAC_ES7148"
|
||||
choice ESP32_KORVO_DU1906_DAC
|
||||
prompt "ESP32 KORVO DU1906 Board DAC chip"
|
||||
depends on ESP32_KORVO_DU1906_BOARD
|
||||
default ESP32_KORVO_DU1906_DAC_TAS5805M
|
||||
help
|
||||
Select DAC chip to use on ESP32_KORVO_DU1906 board
|
||||
|
||||
endchoice
|
||||
config ESP32_KORVO_DU1906_DAC_TAS5805M
|
||||
bool "ESP32_KORVO_DU1906_DAC_TAS5805M"
|
||||
config ESP32_KORVO_DU1906_DAC_ES7148
|
||||
bool "ESP32_KORVO_DU1906_DAC_ES7148"
|
||||
|
||||
choice ESP32_KORVO_DU1906_ADC
|
||||
prompt "ESP32 KORVO DU1906 Board ADC chip"
|
||||
depends on ESP32_KORVO_DU1906_BOARD
|
||||
default ESP32_KORVO_DU1906_ADC_ES7243
|
||||
help
|
||||
Select ADC chip to use on ESP32_KORVO_DU1906 board
|
||||
endchoice
|
||||
|
||||
config ESP32_KORVO_DU1906_ADC_ES7243
|
||||
bool "ESP32_KORVO_DU1906_ADC_ES7243"
|
||||
endchoice
|
||||
choice ESP32_KORVO_DU1906_ADC
|
||||
prompt "ESP32 KORVO DU1906 Board ADC chip"
|
||||
depends on ESP32_KORVO_DU1906_BOARD
|
||||
default ESP32_KORVO_DU1906_ADC_ES7243
|
||||
help
|
||||
Select ADC chip to use on ESP32_KORVO_DU1906 board
|
||||
|
||||
config ESP32_KORVO_DU1906_ADC_ES7243
|
||||
bool "ESP32_KORVO_DU1906_ADC_ES7243"
|
||||
endchoice
|
||||
|
||||
menu "Custom Audio Board"
|
||||
depends on AUDIO_BOARD_CUSTOM
|
||||
|
||||
choice GENERIC_BOARD_DAC
|
||||
prompt "DAC chip"
|
||||
default DAC_MA120
|
||||
help
|
||||
Select a DAC connected to the generic ESP32 board
|
||||
|
||||
config DAC_PCM51XX
|
||||
bool "TI PCM51XX/TAS57XX based DAC"
|
||||
|
||||
config DAC_PCM5102A
|
||||
bool "TI PCM5102A based DAC"
|
||||
|
||||
config DAC_MA120
|
||||
bool "Infineon MA120 ClassD AMP"
|
||||
|
||||
config DAC_MA120X0
|
||||
bool "Infineon MA120X0 ClassD AMP"
|
||||
|
||||
config DAC_ADAU1961
|
||||
bool "Analog Devices ADAU1961 DAC"
|
||||
|
||||
config DAC_MAX98357
|
||||
bool "Analog Devices MAX98357 DAC"
|
||||
|
||||
config DAC_TAS5805M
|
||||
bool "Texas Instruments TAS5805M"
|
||||
|
||||
config DAC_PT8211
|
||||
bool "Princeton Technology PT8211"
|
||||
select I2S_USE_MSB_FORMAT
|
||||
endchoice
|
||||
|
||||
menu "DAC I2C control interface"
|
||||
config DAC_I2C_SDA
|
||||
int "SDA pin"
|
||||
default 12 if DAC_ADAU1961
|
||||
default 21 if DAC_MA120 || DAC_PCM51XX || DAC_MA120 || DAC_MA120X0 || DAC_MAX98357 || DAC_PCM5102A || DAC_TAS5805M
|
||||
default -1 if DAC_PT8211
|
||||
help
|
||||
I2C SDA pin of the DAC control interface
|
||||
config DAC_I2C_SCL
|
||||
int "SCL pin"
|
||||
default 14 if DAC_ADAU1961
|
||||
default 22 if DAC_MA120 || DAC_PCM51XX || DAC_MA120 || DAC_MA120X0 || DAC_MAX98357 || DAC_PCM5102A
|
||||
default 27 if DAC_TAS5805M
|
||||
default -1 if DAC_PT8211
|
||||
help
|
||||
I2C SCL pin of the DAC control interface
|
||||
config DAC_I2C_ADDR
|
||||
hex "I2C address"
|
||||
default 0x70 if DAC_ADAU1961
|
||||
default 0x20 if DAC_MA120 || DAC_PCM51XX || DAC_MA120 || DAC_MA120X0 || DAC_MAX98357 || DAC_PCM5102A
|
||||
default 0x2D if DAC_TAS5805M
|
||||
default 0x00 if DAC_PT8211
|
||||
help
|
||||
I2C Address of the DAC control interface
|
||||
endmenu
|
||||
|
||||
menu "I2S master interface"
|
||||
config MASTER_I2S_MCLK_PIN
|
||||
int "Master i2s mclk"
|
||||
default 3 if DAC_ADAU1961
|
||||
default 0
|
||||
help
|
||||
Master audio interface master clock.
|
||||
|
||||
config MASTER_I2S_BCK_PIN
|
||||
int "Master i2s bck"
|
||||
default 15 if DAC_ADAU1961
|
||||
default 23 if DAC_MAX98357
|
||||
default 26 if DAC_TAS5805M
|
||||
default 23
|
||||
|
||||
help
|
||||
Master audio interface bit clock.
|
||||
|
||||
config MASTER_I2S_LRCK_PIN
|
||||
int "Master i2s lrck"
|
||||
default 13 if DAC_ADAU1961
|
||||
default 24 if DAC_MAX98357
|
||||
default 25 if DAC_TAS5805M
|
||||
default 2
|
||||
help
|
||||
Master audio interface left/right sync clock.
|
||||
|
||||
config MASTER_I2S_DATAOUT_PIN
|
||||
int "Master i2s data out"
|
||||
default 4 if DAC_ADAU1961
|
||||
default 25 if DAC_MAX98357
|
||||
default 22 if DAC_TAS5805M
|
||||
default 14
|
||||
help
|
||||
Master audio interface data out.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "DAC-Operation-Mode"
|
||||
depends on DAC_TAS5805M
|
||||
|
||||
config DAC_BRIDGE_MODE
|
||||
bool "Enable Bridge-Mode"
|
||||
default false if DAC_TAS5805M
|
||||
help
|
||||
If enabled left channel will be played with more power. To use the right channel please change Word-Select-Setting in Logic-Level-Settings.
|
||||
endmenu
|
||||
|
||||
menu "I2S slave interface"
|
||||
config SLAVE_I2S_BCK_PIN
|
||||
int "Slave i2s bck"
|
||||
default 26
|
||||
help
|
||||
Slave audio interface bit clock.
|
||||
config SLAVE_I2S_MCLK_PIN
|
||||
int "Slave i2s mclk"
|
||||
default 0
|
||||
help
|
||||
Slave audio interface bit clock.
|
||||
config SLAVE_I2S_LRCK_PIN
|
||||
int "Slave i2s lrck"
|
||||
default 12
|
||||
help
|
||||
Slave audio interface left/right sync clock.
|
||||
|
||||
config SLAVE_I2S_DATAOUT_PIN
|
||||
int "Slave i2s data out"
|
||||
default 5
|
||||
help
|
||||
Slave audio interface data out.
|
||||
endmenu
|
||||
|
||||
menu "Merus MA120x0 interface Configuration"
|
||||
depends on DAC_MA120X0
|
||||
|
||||
config MA120X0_NENABLE_PIN
|
||||
int "Master enable/disable for ma120x0"
|
||||
default 16
|
||||
help
|
||||
GPIO number to control enable/disable.
|
||||
|
||||
config MA120X0_NMUTE_PIN
|
||||
int "Master mute/unmute for ma120x0"
|
||||
default 2
|
||||
help
|
||||
GPIO number to controm mute/unmute.
|
||||
|
||||
config MERUS_NERR_PIN
|
||||
int "NERR monitor pin"
|
||||
default 21
|
||||
help
|
||||
GPIO number to monitor NERROR.
|
||||
|
||||
config MERUS_NCLIP_PIN
|
||||
int "Clip indication pin"
|
||||
default 22
|
||||
help
|
||||
GPIO number low if clip observed
|
||||
endmenu
|
||||
|
||||
menu "Merus MA120 interface Configuration"
|
||||
depends on DAC_MA120
|
||||
|
||||
config MA120_ENABLE_PIN
|
||||
int "Master enable/disable for ma120x0"
|
||||
default 16
|
||||
help
|
||||
GPIO number to control enable/disable.
|
||||
|
||||
config MA120_NMUTE_PIN
|
||||
int "Master mute/unmute for ma120x0"
|
||||
default 2
|
||||
help
|
||||
GPIO number to controm mute/unmute.
|
||||
|
||||
config MERUS_NERR_PIN
|
||||
int "NERR monitor pin"
|
||||
default 21
|
||||
help
|
||||
GPIO number to monitor NERROR.
|
||||
|
||||
config MERUS_NCLIP_PIN
|
||||
int "Clip indication pin"
|
||||
default 22
|
||||
help
|
||||
GPIO number low if clip observed
|
||||
endmenu
|
||||
|
||||
menu "TI PCM5102A interface Configuration"
|
||||
depends on DAC_PCM5102A
|
||||
|
||||
config PCM5102A_MUTE_PIN
|
||||
int "Master mute/unmute for PCM5102A"
|
||||
default 18
|
||||
help
|
||||
GPIO number to control mute/unmute.
|
||||
This is labeled "X(S)MT" on chip/boards
|
||||
endmenu
|
||||
|
||||
menu "MAX98357 interface Configuration"
|
||||
depends on DAC_MAX98357
|
||||
|
||||
config MAX98357_MUTE_PIN
|
||||
int "Master mute/mode for MAX98357"
|
||||
default 18
|
||||
help
|
||||
GPIO number to control mute/mode. This require a special resistor to select the correct mode.
|
||||
You need to put a serie resistor to select the mode (GPIO --> Resistor --> SD):
|
||||
LEFT only : 0ohm (direct connection)
|
||||
RIGHT only : 220Kohm
|
||||
(L+R)/2 : 1Mohm
|
||||
Refer to Analog Devices' doc for more infos.
|
||||
This is labeled "SD" on chip/boards.
|
||||
endmenu
|
||||
|
||||
menu "PT8211 interface Configuration"
|
||||
depends on DAC_PT8211
|
||||
|
||||
config PT8211_MUTE_PIN
|
||||
int "Master mute/unmute"
|
||||
default -1
|
||||
help
|
||||
GPIO number to control mute/unmute.
|
||||
Note that PT8211 does not have a mute control pin. This output is intended to control external circuit (e.g., amplifier).
|
||||
|
||||
config PT8211_MUTE_ACTIVE_LOW
|
||||
bool "Mute active LOW"
|
||||
default false
|
||||
help
|
||||
Output LOW instead of HIGH on mute/unmute pin when in mute state.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Logic-Level-Settings"
|
||||
config INVERT_MCLK_LEVEL
|
||||
bool "Invert Logic Level MCLK"
|
||||
default false
|
||||
help
|
||||
Invert the Logic-Level of MCLK.
|
||||
config INVERT_WORD_SELECT_LEVEL
|
||||
bool "Invert Logic Level WordSelect"
|
||||
default false
|
||||
help
|
||||
Some Dacs can bridge their outputs. Word-Select is used for selecting the played audio channel. This will switch L/R.
|
||||
config INVERT_BCLK_LEVEL
|
||||
bool "Invert Logic Level BCLK"
|
||||
default false
|
||||
help
|
||||
Invert the Logic-Level of BCLK.
|
||||
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
|
||||
155
components/audio_board/ai_thinker_es8388/board.c
Normal file
155
components/audio_board/ai_thinker_es8388/board.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2019 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in
|
||||
* which case, it is free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "board.h"
|
||||
#include "audio_mem.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
//#include "periph_sdcard.h"
|
||||
//#include "led_indicator.h"
|
||||
//#include "periph_touch.h"
|
||||
//#include "periph_button.h"
|
||||
|
||||
static const char *TAG = "AUDIO_BOARD";
|
||||
|
||||
static audio_board_handle_t board_handle = 0;
|
||||
|
||||
audio_board_handle_t
|
||||
audio_board_init (void)
|
||||
{
|
||||
if (board_handle)
|
||||
{
|
||||
ESP_LOGW (TAG, "The board has already been initialized!");
|
||||
return board_handle;
|
||||
}
|
||||
board_handle = (audio_board_handle_t)audio_calloc (
|
||||
1, sizeof (struct audio_board_handle));
|
||||
AUDIO_MEM_CHECK (TAG, board_handle, return NULL);
|
||||
board_handle->audio_hal = audio_board_codec_init ();
|
||||
|
||||
return board_handle;
|
||||
}
|
||||
|
||||
audio_hal_handle_t
|
||||
audio_board_codec_init (void)
|
||||
{
|
||||
audio_hal_codec_config_t audio_codec_cfg = AUDIO_CODEC_DEFAULT_CONFIG ();
|
||||
audio_hal_handle_t codec_hal
|
||||
= audio_hal_init (&audio_codec_cfg, &AUDIO_CODEC_ES8388_DEFAULT_HANDLE);
|
||||
AUDIO_NULL_CHECK (TAG, codec_hal, return NULL);
|
||||
return codec_hal;
|
||||
}
|
||||
|
||||
/*
|
||||
display_service_handle_t audio_board_led_init(void)
|
||||
{
|
||||
led_indicator_handle_t led =
|
||||
led_indicator_init((gpio_num_t)get_green_led_gpio()); display_service_config_t
|
||||
display = { .based_cfg = { .task_stack = 0, .task_prio = 0, .task_core = 0,
|
||||
.task_func = NULL,
|
||||
.service_start = NULL,
|
||||
.service_stop = NULL,
|
||||
.service_destroy = NULL,
|
||||
.service_ioctl = led_indicator_pattern,
|
||||
.service_name = "DISPLAY_serv",
|
||||
.user_data = NULL,
|
||||
},
|
||||
.instance = led,
|
||||
};
|
||||
|
||||
return display_service_create(&display);
|
||||
}
|
||||
|
||||
esp_err_t audio_board_key_init(esp_periph_set_handle_t set)
|
||||
{
|
||||
periph_button_cfg_t btn_cfg = {
|
||||
.gpio_mask = (1ULL << get_input_rec_id()) | (1ULL <<
|
||||
get_input_mode_id()), //REC BTN & MODE BTN
|
||||
};
|
||||
esp_periph_handle_t button_handle = periph_button_init(&btn_cfg);
|
||||
AUDIO_NULL_CHECK(TAG, button_handle, return ESP_ERR_ADF_MEMORY_LACK);
|
||||
esp_err_t ret = ESP_OK;
|
||||
ret = esp_periph_start(set, button_handle);
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
periph_touch_cfg_t touch_cfg = {
|
||||
.touch_mask = TOUCH_PAD_SEL4 | TOUCH_PAD_SEL7 | TOUCH_PAD_SEL8 |
|
||||
TOUCH_PAD_SEL9, .tap_threshold_percent = 70,
|
||||
};
|
||||
esp_periph_handle_t touch_periph = periph_touch_init(&touch_cfg);
|
||||
AUDIO_NULL_CHECK(TAG, touch_periph, return ESP_ERR_ADF_MEMORY_LACK);
|
||||
ret = esp_periph_start(set, touch_periph);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t audio_board_sdcard_init(esp_periph_set_handle_t set,
|
||||
periph_sdcard_mode_t mode)
|
||||
{
|
||||
if (mode >= SD_MODE_MAX) {
|
||||
ESP_LOGE(TAG, "PLease select the correct sd mode!, current mode is %d",
|
||||
mode); return ESP_FAIL;
|
||||
}
|
||||
periph_sdcard_cfg_t sdcard_cfg = {
|
||||
.root = "/sdcard",
|
||||
.card_detect_pin = get_sdcard_intr_gpio(), // GPIO_NUM_34
|
||||
.mode = mode,
|
||||
};
|
||||
esp_periph_handle_t sdcard_handle = periph_sdcard_init(&sdcard_cfg);
|
||||
esp_err_t ret = esp_periph_start(set, sdcard_handle);
|
||||
int retry_time = 5;
|
||||
bool mount_flag = false;
|
||||
while (retry_time --) {
|
||||
if (periph_sdcard_is_mounted(sdcard_handle)) {
|
||||
mount_flag = true;
|
||||
break;
|
||||
} else {
|
||||
vTaskDelay(500 / portTICK_PERIOD_MS);
|
||||
}
|
||||
}
|
||||
if (mount_flag == false) {
|
||||
ESP_LOGE(TAG, "Sdcard mount failed");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
|
||||
audio_board_handle_t
|
||||
audio_board_get_handle (void)
|
||||
{
|
||||
return board_handle;
|
||||
}
|
||||
|
||||
esp_err_t
|
||||
audio_board_deinit (audio_board_handle_t audio_board)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
ret = audio_hal_deinit (audio_board->audio_hal);
|
||||
audio_free (audio_board);
|
||||
board_handle = NULL;
|
||||
return ret;
|
||||
}
|
||||
117
components/audio_board/ai_thinker_es8388/board.h
Normal file
117
components/audio_board/ai_thinker_es8388/board.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2019 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in
|
||||
* which case, it is free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AUDIO_BOARD_H_
|
||||
#define _AUDIO_BOARD_H_
|
||||
|
||||
#include "audio_hal.h"
|
||||
#include "board_def.h"
|
||||
#include "board_pins_config.h"
|
||||
//#include "esp_peripherals.h"
|
||||
//#include "display_service.h"
|
||||
//#include "periph_sdcard.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Audio board handle
|
||||
*/
|
||||
struct audio_board_handle
|
||||
{
|
||||
audio_hal_handle_t audio_hal; /*!< audio hardware abstract layer handle */
|
||||
};
|
||||
|
||||
typedef struct audio_board_handle *audio_board_handle_t;
|
||||
|
||||
/**
|
||||
* @brief Initialize audio board
|
||||
*
|
||||
* @return The audio board handle
|
||||
*/
|
||||
audio_board_handle_t audio_board_init (void);
|
||||
|
||||
/**
|
||||
* @brief Initialize codec chip
|
||||
*
|
||||
* @return The audio hal handle
|
||||
*/
|
||||
audio_hal_handle_t audio_board_codec_init (void);
|
||||
|
||||
///**
|
||||
// * @brief Initialize led peripheral and display service
|
||||
// *
|
||||
// * @return The audio display service handle
|
||||
// */
|
||||
// display_service_handle_t audio_board_led_init(void);
|
||||
//
|
||||
///**
|
||||
// * @brief Initialize key peripheral
|
||||
// *
|
||||
// * @param set The handle of esp_periph_set_handle_t
|
||||
// *
|
||||
// * @return
|
||||
// * - ESP_OK, success
|
||||
// * - Others, fail
|
||||
// */
|
||||
// esp_err_t audio_board_key_init(esp_periph_set_handle_t set);
|
||||
//
|
||||
///**
|
||||
// * @brief Initialize sdcard peripheral
|
||||
// *
|
||||
// * @param set The handle of esp_periph_set_handle_t
|
||||
// *
|
||||
// * @return
|
||||
// * - ESP_OK, success
|
||||
// * - Others, fail
|
||||
// */
|
||||
// esp_err_t audio_board_sdcard_init(esp_periph_set_handle_t set,
|
||||
// periph_sdcard_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Query audio_board_handle
|
||||
*
|
||||
* @return The audio board handle
|
||||
*/
|
||||
audio_board_handle_t audio_board_get_handle (void);
|
||||
|
||||
/**
|
||||
* @brief Uninitialize the audio board
|
||||
*
|
||||
* @param audio_board The handle of audio board
|
||||
*
|
||||
* @return 0 success,
|
||||
* others fail
|
||||
*/
|
||||
esp_err_t audio_board_deinit (audio_board_handle_t audio_board);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
103
components/audio_board/ai_thinker_es8388/board_def.h
Normal file
103
components/audio_board/ai_thinker_es8388/board_def.h
Normal file
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2019 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in
|
||||
* which case, it is free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _AUDIO_BOARD_DEFINITION_H_
|
||||
#define _AUDIO_BOARD_DEFINITION_H_
|
||||
|
||||
#include "driver/touch_pad.h"
|
||||
|
||||
#define SDCARD_OPEN_FILE_NUM_MAX 5
|
||||
#define SDCARD_INTR_GPIO GPIO_NUM_34
|
||||
|
||||
#define BUTTON_REC_ID GPIO_NUM_36
|
||||
#define BUTTON_MODE_ID GPIO_NUM_39
|
||||
#define BUTTON_SET_ID TOUCH_PAD_NUM9
|
||||
#define BUTTON_PLAY_ID TOUCH_PAD_NUM8
|
||||
#define BUTTON_VOLUP_ID TOUCH_PAD_NUM7
|
||||
#define BUTTON_VOLDOWN_ID TOUCH_PAD_NUM4
|
||||
|
||||
#define AUXIN_DETECT_GPIO GPIO_NUM_12
|
||||
#define HEADPHONE_DETECT GPIO_NUM_19
|
||||
#define PA_ENABLE_GPIO GPIO_NUM_21
|
||||
#define BOARD_PA_GAIN (10) /* Power amplifier gain defined by board (dB) */
|
||||
|
||||
#define GREEN_LED_GPIO GPIO_NUM_22
|
||||
|
||||
extern audio_hal_func_t AUDIO_CODEC_ES8388_DEFAULT_HANDLE;
|
||||
|
||||
#define AUDIO_CODEC_DEFAULT_CONFIG() \
|
||||
{ \
|
||||
.adc_input = AUDIO_HAL_ADC_INPUT_LINE1, \
|
||||
.dac_output = AUDIO_HAL_DAC_OUTPUT_ALL, \
|
||||
.codec_mode = AUDIO_HAL_CODEC_MODE_BOTH, \
|
||||
.i2s_iface = \
|
||||
{ \
|
||||
.mode = AUDIO_HAL_MODE_SLAVE, \
|
||||
.fmt = AUDIO_HAL_I2S_NORMAL, \
|
||||
.samples = AUDIO_HAL_48K_SAMPLES, \
|
||||
.bits = AUDIO_HAL_BIT_LENGTH_16BITS, \
|
||||
}, \
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Button Function Definition
|
||||
*/
|
||||
#define INPUT_KEY_NUM 6
|
||||
|
||||
#define INPUT_KEY_DEFAULT_INFO() \
|
||||
{ \
|
||||
{ \
|
||||
.type = PERIPH_ID_BUTTON, \
|
||||
.user_id = INPUT_KEY_USER_ID_REC, \
|
||||
.act_id = BUTTON_REC_ID, \
|
||||
}, \
|
||||
{ \
|
||||
.type = PERIPH_ID_BUTTON, \
|
||||
.user_id = INPUT_KEY_USER_ID_MODE, \
|
||||
.act_id = BUTTON_MODE_ID, \
|
||||
}, \
|
||||
{ \
|
||||
.type = PERIPH_ID_TOUCH, \
|
||||
.user_id = INPUT_KEY_USER_ID_SET, \
|
||||
.act_id = BUTTON_SET_ID, \
|
||||
}, \
|
||||
{ \
|
||||
.type = PERIPH_ID_TOUCH, \
|
||||
.user_id = INPUT_KEY_USER_ID_PLAY, \
|
||||
.act_id = BUTTON_PLAY_ID, \
|
||||
}, \
|
||||
{ \
|
||||
.type = PERIPH_ID_TOUCH, \
|
||||
.user_id = INPUT_KEY_USER_ID_VOLUP, \
|
||||
.act_id = BUTTON_VOLUP_ID, \
|
||||
}, \
|
||||
{ \
|
||||
.type = PERIPH_ID_TOUCH, .user_id = INPUT_KEY_USER_ID_VOLDOWN, \
|
||||
.act_id = BUTTON_VOLDOWN_ID, \
|
||||
} \
|
||||
}
|
||||
|
||||
#endif
|
||||
117
components/audio_board/ai_thinker_es8388/board_pins_config.c
Normal file
117
components/audio_board/ai_thinker_es8388/board_pins_config.c
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2019 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in
|
||||
* which case, it is free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "audio_error.h"
|
||||
#include "audio_mem.h"
|
||||
#include "board.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
static const char *TAG = "AI_THINKER_ES8388";
|
||||
|
||||
esp_err_t get_i2c_pins(i2c_port_t port, i2c_config_t *i2c_config) {
|
||||
AUDIO_NULL_CHECK(TAG, i2c_config, return ESP_FAIL);
|
||||
if (port == I2C_NUM_0 || port == I2C_NUM_1) {
|
||||
i2c_config->sda_io_num = GPIO_NUM_33;
|
||||
i2c_config->scl_io_num = GPIO_NUM_32;
|
||||
} else {
|
||||
i2c_config->sda_io_num = -1;
|
||||
i2c_config->scl_io_num = -1;
|
||||
ESP_LOGE(TAG, "i2c port %d is not supported", port);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t get_i2s_pins(i2s_port_t port, board_i2s_pin_t *i2s_config) {
|
||||
AUDIO_NULL_CHECK(TAG, i2s_config, return ESP_FAIL);
|
||||
if (port == I2S_NUM_0 || port == I2S_NUM_1) {
|
||||
i2s_config->mck_io_num = GPIO_NUM_0;
|
||||
i2s_config->bck_io_num = GPIO_NUM_27;
|
||||
i2s_config->ws_io_num = GPIO_NUM_25;
|
||||
i2s_config->data_out_num = GPIO_NUM_26;
|
||||
i2s_config->data_in_num = GPIO_NUM_35;
|
||||
} else {
|
||||
memset(i2s_config, -1, sizeof(board_i2s_pin_t));
|
||||
ESP_LOGE(TAG, "i2s port %d is not supported", port);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t get_spi_pins(
|
||||
spi_bus_config_t *spi_config,
|
||||
spi_device_interface_config_t *spi_device_interface_config) {
|
||||
AUDIO_NULL_CHECK(TAG, spi_config, return ESP_FAIL);
|
||||
AUDIO_NULL_CHECK(TAG, spi_device_interface_config, return ESP_FAIL);
|
||||
|
||||
spi_config->mosi_io_num = -1;
|
||||
spi_config->miso_io_num = -1;
|
||||
spi_config->sclk_io_num = -1;
|
||||
spi_config->quadwp_io_num = -1;
|
||||
spi_config->quadhd_io_num = -1;
|
||||
|
||||
spi_device_interface_config->spics_io_num = -1;
|
||||
|
||||
ESP_LOGW(TAG, "SPI interface is not supported");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// sdcard
|
||||
|
||||
int8_t get_sdcard_intr_gpio(void) { return SDCARD_INTR_GPIO; }
|
||||
|
||||
int8_t get_sdcard_open_file_num_max(void) { return SDCARD_OPEN_FILE_NUM_MAX; }
|
||||
|
||||
// input-output pins
|
||||
|
||||
int8_t get_auxin_detect_gpio(void) { return AUXIN_DETECT_GPIO; }
|
||||
|
||||
int8_t get_headphone_detect_gpio(void) { return HEADPHONE_DETECT; }
|
||||
|
||||
int8_t get_pa_enable_gpio(void) { return PA_ENABLE_GPIO; }
|
||||
|
||||
// button pins
|
||||
|
||||
int8_t get_input_rec_id(void) { return BUTTON_REC_ID; }
|
||||
|
||||
int8_t get_input_mode_id(void) { return BUTTON_MODE_ID; }
|
||||
|
||||
// touch pins
|
||||
|
||||
int8_t get_input_set_id(void) { return BUTTON_SET_ID; }
|
||||
|
||||
int8_t get_input_play_id(void) { return BUTTON_PLAY_ID; }
|
||||
|
||||
int8_t get_input_volup_id(void) { return BUTTON_VOLUP_ID; }
|
||||
|
||||
int8_t get_input_voldown_id(void) { return BUTTON_VOLDOWN_ID; }
|
||||
|
||||
// led pins
|
||||
|
||||
int8_t get_green_led_gpio(void) { return GREEN_LED_GPIO; }
|
||||
@@ -51,3 +51,8 @@ ifdef CONFIG_ESP32_C3_LYRA_V2_BOARD
|
||||
COMPONENT_ADD_INCLUDEDIRS += ./esp32_c3_lyra
|
||||
COMPONENT_SRCDIRS += ./esp32_c3_lyra
|
||||
endif
|
||||
|
||||
ifdef CONFIG_ESP_AI_THINKER_ES8388_BOARD
|
||||
COMPONENT_ADD_INCLUDEDIRS += ./ai_thinker_es8388
|
||||
COMPONENT_SRCDIRS += ./ai_thinker_es8388
|
||||
endif
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
#include "audio_mem.h"
|
||||
#include "esp_log.h"
|
||||
#include "periph_adc_button.h"
|
||||
// #include "periph_adc_button.h"
|
||||
|
||||
static const char *TAG = "AUDIO_BOARD";
|
||||
|
||||
@@ -61,80 +61,81 @@ esp_err_t audio_board_sdcard_init(esp_periph_set_handle_t set,
|
||||
return ret;
|
||||
}
|
||||
|
||||
display_service_handle_t audio_board_led_init(void) {
|
||||
// TODO
|
||||
return NULL;
|
||||
}
|
||||
#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0))
|
||||
esp_err_t _get_lcd_io_bus(void *bus, esp_lcd_panel_io_spi_config_t *io_config,
|
||||
esp_lcd_panel_io_handle_t *out_panel_io) {
|
||||
return esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)bus, io_config,
|
||||
out_panel_io);
|
||||
}
|
||||
|
||||
void *audio_board_lcd_init(esp_periph_set_handle_t set, void *cb) {
|
||||
gpio_config_t bk_gpio_config = {.mode = GPIO_MODE_OUTPUT,
|
||||
.pin_bit_mask = 1ULL << LCD_CTRL_GPIO};
|
||||
// Initialize the GPIO of backlight
|
||||
ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
|
||||
|
||||
spi_bus_config_t buscfg = {.sclk_io_num = LCD_CLK_GPIO,
|
||||
.mosi_io_num = LCD_MOSI_GPIO,
|
||||
.miso_io_num = -1,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
.max_transfer_sz = 16 * LCD_H_RES * 2 + 8};
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));
|
||||
|
||||
esp_lcd_panel_io_spi_config_t io_config = {
|
||||
.dc_gpio_num = LCD_DC_GPIO,
|
||||
.cs_gpio_num = LCD_CS_GPIO,
|
||||
.pclk_hz = 60 * 1000 * 1000,
|
||||
.lcd_cmd_bits = 8,
|
||||
.lcd_param_bits = 8,
|
||||
.spi_mode = 0,
|
||||
.trans_queue_depth = 10,
|
||||
.on_color_trans_done = cb,
|
||||
.user_ctx = NULL,
|
||||
};
|
||||
esp_lcd_panel_dev_config_t panel_config = {
|
||||
.reset_gpio_num = LCD_RST_GPIO,
|
||||
.color_space = ESP_LCD_COLOR_SPACE_BGR,
|
||||
.bits_per_pixel = 16,
|
||||
};
|
||||
periph_lcd_cfg_t cfg = {
|
||||
.io_bus = (void *)SPI2_HOST,
|
||||
.new_panel_io = _get_lcd_io_bus,
|
||||
.lcd_io_cfg = &io_config,
|
||||
.new_lcd_panel = esp_lcd_new_panel_st7789,
|
||||
.lcd_dev_cfg = &panel_config,
|
||||
.rest_cb = NULL,
|
||||
.rest_cb_ctx = NULL,
|
||||
.lcd_swap_xy = LCD_SWAP_XY,
|
||||
.lcd_mirror_x = LCD_MIRROR_X,
|
||||
.lcd_mirror_y = LCD_MIRROR_Y,
|
||||
.lcd_color_invert = LCD_COLOR_INV,
|
||||
};
|
||||
esp_periph_handle_t periph_lcd = periph_lcd_init(&cfg);
|
||||
AUDIO_NULL_CHECK(TAG, periph_lcd, return NULL);
|
||||
esp_periph_start(set, periph_lcd);
|
||||
return (void *)periph_lcd_get_panel_handle(periph_lcd);
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t audio_board_key_init(esp_periph_set_handle_t set) {
|
||||
periph_adc_button_cfg_t adc_btn_cfg = PERIPH_ADC_BUTTON_DEFAULT_CONFIG();
|
||||
adc_arr_t adc_btn_tag = ADC_DEFAULT_ARR();
|
||||
adc_btn_tag.adc_ch = ADC1_CHANNEL_5;
|
||||
adc_btn_tag.total_steps = 6;
|
||||
int btn_array[7] = {190, 600, 1000, 1375, 1775, 2195, 2610};
|
||||
adc_btn_tag.adc_level_step = btn_array;
|
||||
adc_btn_cfg.arr = &adc_btn_tag;
|
||||
adc_btn_cfg.arr_size = 1;
|
||||
esp_periph_handle_t adc_btn_handle = periph_adc_button_init(&adc_btn_cfg);
|
||||
AUDIO_NULL_CHECK(TAG, adc_btn_handle, return ESP_ERR_ADF_MEMORY_LACK);
|
||||
return esp_periph_start(set, adc_btn_handle);
|
||||
}
|
||||
// display_service_handle_t audio_board_led_init(void) {
|
||||
// // TODO
|
||||
// return NULL;
|
||||
// }
|
||||
// #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 4, 0))
|
||||
// esp_err_t _get_lcd_io_bus(void *bus, esp_lcd_panel_io_spi_config_t
|
||||
// *io_config,
|
||||
// esp_lcd_panel_io_handle_t *out_panel_io) {
|
||||
// return esp_lcd_new_panel_io_spi((esp_lcd_spi_bus_handle_t)bus, io_config,
|
||||
// out_panel_io);
|
||||
// }
|
||||
//
|
||||
// void *audio_board_lcd_init(esp_periph_set_handle_t set, void *cb) {
|
||||
// gpio_config_t bk_gpio_config = {.mode = GPIO_MODE_OUTPUT,
|
||||
// .pin_bit_mask = 1ULL << LCD_CTRL_GPIO};
|
||||
// // Initialize the GPIO of backlight
|
||||
// ESP_ERROR_CHECK(gpio_config(&bk_gpio_config));
|
||||
//
|
||||
// spi_bus_config_t buscfg = {.sclk_io_num = LCD_CLK_GPIO,
|
||||
// .mosi_io_num = LCD_MOSI_GPIO,
|
||||
// .miso_io_num = -1,
|
||||
// .quadwp_io_num = -1,
|
||||
// .quadhd_io_num = -1,
|
||||
// .max_transfer_sz = 16 * LCD_H_RES * 2 + 8};
|
||||
// ESP_ERROR_CHECK(spi_bus_initialize(SPI2_HOST, &buscfg, SPI_DMA_CH_AUTO));
|
||||
//
|
||||
// esp_lcd_panel_io_spi_config_t io_config = {
|
||||
// .dc_gpio_num = LCD_DC_GPIO,
|
||||
// .cs_gpio_num = LCD_CS_GPIO,
|
||||
// .pclk_hz = 60 * 1000 * 1000,
|
||||
// .lcd_cmd_bits = 8,
|
||||
// .lcd_param_bits = 8,
|
||||
// .spi_mode = 0,
|
||||
// .trans_queue_depth = 10,
|
||||
// .on_color_trans_done = cb,
|
||||
// .user_ctx = NULL,
|
||||
// };
|
||||
// esp_lcd_panel_dev_config_t panel_config = {
|
||||
// .reset_gpio_num = LCD_RST_GPIO,
|
||||
// .color_space = ESP_LCD_COLOR_SPACE_BGR,
|
||||
// .bits_per_pixel = 16,
|
||||
// };
|
||||
// periph_lcd_cfg_t cfg = {
|
||||
// .io_bus = (void *)SPI2_HOST,
|
||||
// .new_panel_io = _get_lcd_io_bus,
|
||||
// .lcd_io_cfg = &io_config,
|
||||
// .new_lcd_panel = esp_lcd_new_panel_st7789,
|
||||
// .lcd_dev_cfg = &panel_config,
|
||||
// .rest_cb = NULL,
|
||||
// .rest_cb_ctx = NULL,
|
||||
// .lcd_swap_xy = LCD_SWAP_XY,
|
||||
// .lcd_mirror_x = LCD_MIRROR_X,
|
||||
// .lcd_mirror_y = LCD_MIRROR_Y,
|
||||
// .lcd_color_invert = LCD_COLOR_INV,
|
||||
// };
|
||||
// esp_periph_handle_t periph_lcd = periph_lcd_init(&cfg);
|
||||
// AUDIO_NULL_CHECK(TAG, periph_lcd, return NULL);
|
||||
// esp_periph_start(set, periph_lcd);
|
||||
// return (void *)periph_lcd_get_panel_handle(periph_lcd);
|
||||
// }
|
||||
// #endif
|
||||
//
|
||||
// esp_err_t audio_board_key_init(esp_periph_set_handle_t set) {
|
||||
// periph_adc_button_cfg_t adc_btn_cfg = PERIPH_ADC_BUTTON_DEFAULT_CONFIG();
|
||||
// adc_arr_t adc_btn_tag = ADC_DEFAULT_ARR();
|
||||
// adc_btn_tag.adc_ch = ADC1_CHANNEL_5;
|
||||
// adc_btn_tag.total_steps = 6;
|
||||
// int btn_array[7] = {190, 600, 1000, 1375, 1775, 2195, 2610};
|
||||
// adc_btn_tag.adc_level_step = btn_array;
|
||||
// adc_btn_cfg.arr = &adc_btn_tag;
|
||||
// adc_btn_cfg.arr_size = 1;
|
||||
// esp_periph_handle_t adc_btn_handle = periph_adc_button_init(&adc_btn_cfg);
|
||||
// AUDIO_NULL_CHECK(TAG, adc_btn_handle, return ESP_ERR_ADF_MEMORY_LACK);
|
||||
// return esp_periph_start(set, adc_btn_handle);
|
||||
// }
|
||||
|
||||
audio_board_handle_t audio_board_get_handle(void) { return board_handle; }
|
||||
|
||||
|
||||
@@ -30,10 +30,10 @@
|
||||
#include "audio_hal.h"
|
||||
#include "board_def.h"
|
||||
#include "board_pins_config.h"
|
||||
#include "display_service.h"
|
||||
#include "esp_peripherals.h"
|
||||
#include "periph_lcd.h"
|
||||
#include "periph_sdcard.h"
|
||||
// #include "display_service.h"
|
||||
// #include "esp_peripherals.h"
|
||||
// #include "periph_lcd.h"
|
||||
// #include "periph_sdcard.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@@ -67,7 +67,7 @@ audio_hal_handle_t audio_board_codec_init(void);
|
||||
*
|
||||
* @return The audio display service handle
|
||||
*/
|
||||
display_service_handle_t audio_board_led_init(void);
|
||||
// display_service_handle_t audio_board_led_init(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize lcd peripheral
|
||||
@@ -78,7 +78,7 @@ display_service_handle_t audio_board_led_init(void);
|
||||
*
|
||||
* @return The `esp_lcd_panel_handle_t` handle
|
||||
*/
|
||||
void *audio_board_lcd_init(esp_periph_set_handle_t set, void *cb);
|
||||
// void *audio_board_lcd_init(esp_periph_set_handle_t set, void *cb);
|
||||
|
||||
/**
|
||||
* @brief Initialize sdcard peripheral
|
||||
@@ -89,8 +89,8 @@ void *audio_board_lcd_init(esp_periph_set_handle_t set, void *cb);
|
||||
* - ESP_OK, success
|
||||
* - Others, fail
|
||||
*/
|
||||
esp_err_t audio_board_sdcard_init(esp_periph_set_handle_t set,
|
||||
periph_sdcard_mode_t mode);
|
||||
// esp_err_t audio_board_sdcard_init(esp_periph_set_handle_t set,
|
||||
// periph_sdcard_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Initialize key peripheral
|
||||
@@ -101,7 +101,7 @@ esp_err_t audio_board_sdcard_init(esp_periph_set_handle_t set,
|
||||
* - ESP_OK, success
|
||||
* - Others, fail
|
||||
*/
|
||||
esp_err_t audio_board_key_init(esp_periph_set_handle_t set);
|
||||
// esp_err_t audio_board_key_init(esp_periph_set_handle_t set);
|
||||
|
||||
/**
|
||||
* @brief Query audio_board_handle
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
#include "esp_log.h"
|
||||
#include "i2c_bus.h"
|
||||
|
||||
#ifdef CONFIG_ESP_LYRAT_V4_3_BOARD
|
||||
#if defined(CONFIG_ESP_LYRAT_V4_3_BOARD) || \
|
||||
defined(CONFIG_ESP_AI_THINKER_ES8388_BOARD)
|
||||
#include "headphone_detect.h"
|
||||
#endif
|
||||
|
||||
@@ -266,11 +267,16 @@ esp_err_t es8388_i2s_config_clock(es_i2s_clock_t cfg) {
|
||||
|
||||
esp_err_t es8388_deinit(void) {
|
||||
int res = 0;
|
||||
|
||||
res = es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER,
|
||||
0xFF); // reset and stop es8388
|
||||
i2c_bus_delete(i2c_handle);
|
||||
#ifdef CONFIG_ESP_LYRAT_V4_3_BOARD
|
||||
#if defined(CONFIG_ESP_LYRAT_V4_3_BOARD) || \
|
||||
defined(CONFIG_ESP_AI_THINKER_ES8388_BOARD)
|
||||
headphone_detect_deinit();
|
||||
res = es_write_reg(ES8388_ADDR, ES8388_CHIPPOWER,
|
||||
0xFF); // reset and stop es8388
|
||||
i2c_bus_delete(i2c_handle);
|
||||
#endif
|
||||
|
||||
audio_codec_volume_deinit(dac_vol_handle);
|
||||
@@ -284,7 +290,9 @@ esp_err_t es8388_deinit(void) {
|
||||
*/
|
||||
esp_err_t es8388_init(audio_hal_codec_config_t *cfg) {
|
||||
int res = 0;
|
||||
#ifdef CONFIG_ESP_LYRAT_V4_3_BOARD
|
||||
|
||||
#if defined(CONFIG_ESP_LYRAT_V4_3_BOARD) || \
|
||||
defined(CONFIG_ESP_AI_THINKER_ES8388_BOARD)
|
||||
headphone_detect_init(get_headphone_detect_gpio());
|
||||
#endif
|
||||
|
||||
@@ -326,15 +334,15 @@ esp_err_t es8388_init(audio_hal_codec_config_t *cfg) {
|
||||
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL21,
|
||||
0x80); // set internal ADC and DAC use the same LRCK
|
||||
// clock, ADC LRCK as internal LRCK
|
||||
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL23, 0x00); // vroi=0
|
||||
|
||||
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL23, 0x00); // vroi=0
|
||||
res |= es_write_reg(
|
||||
ES8388_ADDR, ES8388_DACCONTROL24,
|
||||
0x1E); // Set L1 R1 L2 R2 volume. 0x00: -30dB, 0x1E: 0dB, 0x21: 3dB
|
||||
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL25, 0x1E);
|
||||
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL26, 0);
|
||||
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL27, 0);
|
||||
// res |= es8388_set_adc_dac_volume(ES_MODULE_DAC, 0, 0); // 0db
|
||||
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL26, 0x1E);
|
||||
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL27, 0x1E);
|
||||
res |= es8388_set_adc_dac_volume(ES_MODULE_DAC, 0, 0); // 0db
|
||||
int tmp = 0;
|
||||
if (AUDIO_HAL_DAC_OUTPUT_LINE2 == cfg->dac_output) {
|
||||
tmp = DAC_OUTPUT_LOUT1 | DAC_OUTPUT_ROUT1;
|
||||
@@ -430,18 +438,41 @@ esp_err_t es8388_config_fmt(es_module_t mode, es_i2s_fmt_t fmt) {
|
||||
esp_err_t es8388_set_voice_volume(int volume) {
|
||||
esp_err_t res = ESP_OK;
|
||||
uint8_t reg = 0;
|
||||
|
||||
reg = audio_codec_get_dac_reg_value(dac_vol_handle, volume);
|
||||
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL5, reg);
|
||||
res |= es_write_reg(ES8388_ADDR, ES8388_DACCONTROL4, reg);
|
||||
ESP_LOGD(ES_TAG, "Set volume:%.2d reg_value:0x%.2x dB:%.1f",
|
||||
(int)dac_vol_handle->user_volume, reg,
|
||||
audio_codec_cal_dac_volume(dac_vol_handle));
|
||||
|
||||
/* Audio Settings can be checked here:
|
||||
* https://dl.radxa.com/rock2/docs/hw/ds/ES8388%20user%20Guide.pdf
|
||||
*
|
||||
* ES8388_DACCONTROL4 & ES8388_DACCONTROL5
|
||||
* 0 = 0dB
|
||||
* 192 = -96dB
|
||||
*
|
||||
* ES8388_DACCONTROL24 - ES8388_DACCONTROL27
|
||||
* 0 = -45dB
|
||||
* 33 = 4.5dB
|
||||
*/
|
||||
|
||||
// restrict range from 0-46 instead of 0-192
|
||||
// int inv_volume = -0.46 * volume + 46;
|
||||
// if (volume == 0) {
|
||||
// // if volume is 0, set to -96dB
|
||||
// inv_volume = 192;
|
||||
// }
|
||||
// res = es_write_reg (ES8388_ADDR, ES8388_DACCONTROL5, inv_volume);
|
||||
// res |= es_write_reg (ES8388_ADDR, ES8388_DACCONTROL4, inv_volume);
|
||||
return res;
|
||||
}
|
||||
|
||||
esp_err_t es8388_get_voice_volume(int *volume) {
|
||||
esp_err_t res = ESP_OK;
|
||||
uint8_t reg = 0;
|
||||
|
||||
res = es_read_reg(ES8388_DACCONTROL4, ®);
|
||||
if (res == ESP_FAIL) {
|
||||
*volume = 0;
|
||||
@@ -454,6 +485,20 @@ esp_err_t es8388_get_voice_volume(int *volume) {
|
||||
}
|
||||
}
|
||||
ESP_LOGD(ES_TAG, "Get volume:%.2d reg_value:0x%.2x", *volume, reg);
|
||||
|
||||
// else
|
||||
// {
|
||||
// // 0 = 0dB, 192 = -96dB
|
||||
// // max is 0, min is 46
|
||||
// // interpolate to 0-100
|
||||
// if (reg == 192) {
|
||||
// *volume = 0;
|
||||
// }
|
||||
// else {
|
||||
// *volume = -(50/23) * reg + 100;
|
||||
// }
|
||||
// }
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
@@ -36,12 +36,13 @@
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/timers.h"
|
||||
|
||||
#ifdef CONFIG_ESP_LYRAT_V4_3_BOARD
|
||||
#if defined(CONFIG_ESP_LYRAT_V4_3_BOARD) || \
|
||||
defined(CONFIG_ESP_AI_THINKER_ES8388_BOARD)
|
||||
|
||||
#define HP_DELAY_TIME_MS 1000
|
||||
|
||||
static const char *TAG = "HEADPHONE";
|
||||
static xTimerHandle timer_headphone;
|
||||
static TimerHandle_t timer_headphone;
|
||||
|
||||
static void hp_timer_cb(TimerHandle_t xTimer) {
|
||||
int num = (int)pvTimerGetTimerID(xTimer);
|
||||
@@ -51,7 +52,7 @@ static void hp_timer_cb(TimerHandle_t xTimer) {
|
||||
|
||||
static int hp_timer_init(int num) {
|
||||
timer_headphone =
|
||||
xTimerCreate("hp_timer0", HP_DELAY_TIME_MS / portTICK_RATE_MS, pdFALSE,
|
||||
xTimerCreate("hp_timer0", HP_DELAY_TIME_MS / portTICK_PERIOD_MS, pdFALSE,
|
||||
(void *)num, hp_timer_cb);
|
||||
if (timer_headphone == NULL) {
|
||||
ESP_LOGE(TAG, "hp_timer create err");
|
||||
@@ -69,7 +70,7 @@ static void IRAM_ATTR headphone_gpio_intr_handler(void *arg) {
|
||||
}
|
||||
|
||||
void headphone_detect_deinit() {
|
||||
xTimerDelete(timer_headphone, HP_DELAY_TIME_MS / portTICK_RATE_MS);
|
||||
xTimerDelete(timer_headphone, HP_DELAY_TIME_MS / portTICK_PERIOD_MS);
|
||||
gpio_uninstall_isr_service();
|
||||
timer_headphone = NULL;
|
||||
}
|
||||
@@ -92,4 +93,5 @@ void headphone_detect_init(int num) {
|
||||
gpio_install_isr_service(0);
|
||||
gpio_isr_handler_add(num, headphone_gpio_intr_handler, (void *)num);
|
||||
}
|
||||
#endif /* CONFIG_ESP_LYRAT_V4_3_BOARD */
|
||||
#endif /* defined(CONFIG_ESP_LYRAT_V4_3_BOARD) || \
|
||||
defined(CONFIG_ESP_AI_THINKER_ES8388_BOARD) */
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "audio_volume.h"
|
||||
#include "board.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/projdefs.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "tas5805m_reg_cfg.h"
|
||||
|
||||
@@ -96,7 +95,7 @@ static esp_err_t tas5805m_transmit_registers(const tas5805m_cfg_reg_t *conf_buf,
|
||||
// Used in legacy applications. Ignored here.
|
||||
break;
|
||||
case CFG_META_DELAY:
|
||||
vTaskDelay(pdMS_TO_TICKS(conf_buf[i].value));
|
||||
vTaskDelay(conf_buf[i].value / portTICK_PERIOD_MS);
|
||||
break;
|
||||
case CFG_META_BURST:
|
||||
ret = i2c_bus_write_bytes(i2c_handler, TAS5805M_ADDR,
|
||||
@@ -136,9 +135,9 @@ esp_err_t tas5805m_init(audio_hal_codec_config_t *codec_cfg) {
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
gpio_config(&io_conf);
|
||||
gpio_set_level(TAS5805M_RST_GPIO, 0);
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
vTaskDelay(20 / portTICK_PERIOD_MS);
|
||||
gpio_set_level(TAS5805M_RST_GPIO, 1);
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
|
||||
ret = get_i2c_pins(I2C_NUM_0, &i2c_cfg);
|
||||
i2c_handler = i2c_bus_create(I2C_NUM_0, &i2c_cfg);
|
||||
|
||||
@@ -17,7 +17,7 @@ if(CONFIG_AUDIO_BOARD_CUSTOM)
|
||||
endif()
|
||||
|
||||
if(CONFIG_DAC_PCM51XX)
|
||||
message(STATUS "Selected DAC is " CONFIG_DAC_PCM15XX)
|
||||
message(STATUS "Selected DAC is " CONFIG_DAC_PCM51XX)
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS ./pcm51xx/include)
|
||||
list(APPEND COMPONENT_SRCS ./pcm51xx/pcm51xx.c)
|
||||
endif()
|
||||
@@ -45,6 +45,18 @@ if(CONFIG_AUDIO_BOARD_CUSTOM)
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS ./max98357/include)
|
||||
list(APPEND COMPONENT_SRCS ./max98357/max98357.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_DAC_TAS5805M)
|
||||
message(STATUS "Selected DAC is " CONFIG_DAC_TAS5805M)
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS ./tas5805m/include)
|
||||
list(APPEND COMPONENT_SRCS ./tas5805m/tas5805m.c)
|
||||
endif()
|
||||
|
||||
if(CONFIG_DAC_PT8211)
|
||||
message(STATUS "Selected DAC is " CONFIG_DAC_PT8211)
|
||||
list(APPEND COMPONENT_ADD_INCLUDEDIRS ./pt8211/include)
|
||||
list(APPEND COMPONENT_SRCS ./pt8211/pt8211.c)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
register_component()
|
||||
|
||||
@@ -1,193 +1 @@
|
||||
menu "Custom Audio Board"
|
||||
depends on AUDIO_BOARD_CUSTOM
|
||||
|
||||
choice GENERIC_BOARD_DAC
|
||||
prompt "DAC chip"
|
||||
default DAC_MA120
|
||||
help
|
||||
Select a DAC connected to the generic ESP32 board
|
||||
|
||||
config DAC_PCM51XX
|
||||
bool "TI PCM51XX/TAS57XX based DAC"
|
||||
|
||||
config DAC_PCM5102A
|
||||
bool "TI PCM5102A based DAC"
|
||||
|
||||
config DAC_MA120
|
||||
bool "Infineon MA120 ClassD AMP"
|
||||
|
||||
config DAC_MA120X0
|
||||
bool "Infineon MA120X0 ClassD AMP"
|
||||
|
||||
config DAC_ADAU1961
|
||||
bool "Analog Devices ADAU1961 DAC"
|
||||
|
||||
config DAC_MAX98357
|
||||
bool "Analog Devices MAX98357 DAC"
|
||||
|
||||
endchoice
|
||||
|
||||
menu "DAC I2C control interface"
|
||||
config DAC_I2C_SDA
|
||||
int "SDA pin"
|
||||
default 12 if DAC_ADAU1961
|
||||
default 21 if DAC_MA120 || DAC_PCM51XX || DAC_MA120 || DAC_MA120X0 || DAC_MAX98357 || DAC_PCM5102A
|
||||
help
|
||||
I2C SDA pin of the DAC control interface
|
||||
config DAC_I2C_SCL
|
||||
int "SCL pin"
|
||||
default 14 if DAC_ADAU1961
|
||||
default 22 if DAC_MA120 || DAC_PCM51XX || DAC_MA120 || DAC_MA120X0 || DAC_MAX98357 || DAC_PCM5102A
|
||||
help
|
||||
I2C SCL pin of the DAC control interface
|
||||
config DAC_I2C_ADDR
|
||||
hex "I2C address"
|
||||
default 0x70 if DAC_ADAU1961
|
||||
default 0x20 if DAC_MA120 || DAC_PCM51XX || DAC_MA120 || DAC_MA120X0 || DAC_MAX98357 || DAC_PCM5102A
|
||||
help
|
||||
I2C Address of the DAC control interface
|
||||
endmenu
|
||||
|
||||
menu "I2S master interface"
|
||||
config MASTER_I2S_MCLK_PIN
|
||||
int "Master i2s mclk"
|
||||
default 3 if DAC_ADAU1961
|
||||
default 0
|
||||
help
|
||||
Master audio interface master clock.
|
||||
|
||||
config MASTER_I2S_BCK_PIN
|
||||
int "Master i2s bck"
|
||||
default 15 if DAC_ADAU1961
|
||||
default 23 if DAC_MAX98357
|
||||
default 23
|
||||
help
|
||||
Master audio interface bit clock.
|
||||
|
||||
config MASTER_I2S_LRCK_PIN
|
||||
int "Master i2s lrck"
|
||||
default 13 if DAC_ADAU1961
|
||||
default 24 if DAC_MAX98357
|
||||
default 13
|
||||
help
|
||||
Master audio interface left/right sync clock.
|
||||
|
||||
config MASTER_I2S_DATAOUT_PIN
|
||||
int "Master i2s data out"
|
||||
default 4 if DAC_ADAU1961
|
||||
default 25 if DAC_MAX98357
|
||||
default 14
|
||||
help
|
||||
Master audio interface data out.
|
||||
endmenu
|
||||
|
||||
menu "I2S slave interface"
|
||||
config SLAVE_I2S_MCLK_PIN
|
||||
int "Slave i2s mclk"
|
||||
default 0
|
||||
help
|
||||
Slave audio interface master clock.
|
||||
|
||||
config SLAVE_I2S_BCK_PIN
|
||||
int "Slave i2s bck"
|
||||
default 26
|
||||
help
|
||||
Slave audio interface bit clock.
|
||||
|
||||
config SLAVE_I2S_LRCK_PIN
|
||||
int "Slave i2s lrck"
|
||||
default 12
|
||||
help
|
||||
Slave audio interface left/right sync clock.
|
||||
|
||||
config SLAVE_I2S_DATAOUT_PIN
|
||||
int "Slave i2s data out"
|
||||
default 5
|
||||
help
|
||||
Slave audio interface data out.
|
||||
endmenu
|
||||
|
||||
menu "Merus MA120x0 interface Configuration"
|
||||
depends on DAC_MA120X0
|
||||
|
||||
config MA120X0_NENABLE_PIN
|
||||
int "Master enable/disable for ma120x0"
|
||||
default 16
|
||||
help
|
||||
GPIO number to control enable/disable.
|
||||
|
||||
config MA120X0_NMUTE_PIN
|
||||
int "Master mute/unmute for ma120x0"
|
||||
default 2
|
||||
help
|
||||
GPIO number to controm mute/unmute.
|
||||
|
||||
config MA120X0_NERR_PIN
|
||||
int "NERR monitor pin"
|
||||
default 21
|
||||
help
|
||||
GPIO number to monitor NERROR.
|
||||
|
||||
config MA120X0_NCLIP_PIN
|
||||
int "Clip indication pin"
|
||||
default 22
|
||||
help
|
||||
GPIO number low if clip observed
|
||||
endmenu
|
||||
|
||||
menu "Merus MA120 interface Configuration"
|
||||
depends on DAC_MA120
|
||||
|
||||
config MA120_ENABLE_PIN
|
||||
int "Master enable/disable for ma120x0"
|
||||
default 16
|
||||
help
|
||||
GPIO number to control enable/disable.
|
||||
|
||||
config MA120_NMUTE_PIN
|
||||
int "Master mute/unmute for ma120x0"
|
||||
default 2
|
||||
help
|
||||
GPIO number to controm mute/unmute.
|
||||
|
||||
config MERUS_NERR_PIN
|
||||
int "NERR monitor pin"
|
||||
default 21
|
||||
help
|
||||
GPIO number to monitor NERROR.
|
||||
|
||||
config MERUS_NCLIP_PIN
|
||||
int "Clip indication pin"
|
||||
default 22
|
||||
help
|
||||
GPIO number low if clip observed
|
||||
endmenu
|
||||
|
||||
menu "TI PCM5102A interface Configuration"
|
||||
depends on DAC_PCM5102A
|
||||
|
||||
config PCM5102A_MUTE_PIN
|
||||
int "Master mute/unmute for PCM5102A"
|
||||
default 18
|
||||
help
|
||||
GPIO number to control mute/unmute.
|
||||
This is labeled "X(S)MT" on chip/boards
|
||||
endmenu
|
||||
|
||||
menu "MAX98357 interface Configuration"
|
||||
depends on DAC_MAX98357
|
||||
|
||||
config MAX98357_MUTE_PIN
|
||||
int "Master mute/mode for MAX98357"
|
||||
default 18
|
||||
help
|
||||
GPIO number to control mute/mode. This require a special resistor to select the correct mode.
|
||||
You need to put a serie resistor to select the mode (GPIO --> Resistor --> SD):
|
||||
LEFT only : 0ohm (direct connection)
|
||||
RIGHT only : 220Kohm
|
||||
(L+R)/2 : 1Mohm
|
||||
Refer to Analog Devices' doc for more infos.
|
||||
This is labeled "SD" on chip/boards.
|
||||
endmenu
|
||||
|
||||
endmenu
|
||||
# this was moved to audio_board
|
||||
|
||||
@@ -27,4 +27,14 @@ COMPONENT_ADD_INCLUDEDIRS += ./max98357/include
|
||||
COMPONENT_SRCDIRS += ./max98357
|
||||
endif
|
||||
|
||||
ifdef CONFIG_DAC_TAS5805M
|
||||
COMPONENT_ADD_INCLUDEDIRS += ./tas5805m/include
|
||||
COMPONENT_SRCDIRS += ./tas5805m
|
||||
endif
|
||||
|
||||
ifdef CONFIG_DAC_PT8211
|
||||
COMPONENT_ADD_INCLUDEDIRS += ./pt8211/include
|
||||
COMPONENT_SRCDIRS += ./pt8211
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
@@ -49,6 +49,12 @@ extern audio_hal_func_t AUDIO_CODEC_ADAU1961_DEFAULT_HANDLE;
|
||||
#elif CONFIG_DAC_MAX98357
|
||||
extern audio_hal_func_t AUDIO_CODEC_MAX98357_DEFAULT_HANDLE;
|
||||
#define AUDIO_CODEC_DEFAULT_HANDLE AUDIO_CODEC_MAX98357_DEFAULT_HANDLE
|
||||
#elif CONFIG_DAC_TAS5805M
|
||||
extern audio_hal_func_t AUDIO_CODEC_TAS5805M_DEFAULT_HANDLE;
|
||||
#define AUDIO_CODEC_DEFAULT_HANDLE AUDIO_CODEC_TAS5805M_DEFAULT_HANDLE
|
||||
#elif CONFIG_DAC_PT8211
|
||||
extern audio_hal_func_t AUDIO_CODEC_PT8211_DEFAULT_HANDLE;
|
||||
#define AUDIO_CODEC_DEFAULT_HANDLE AUDIO_CODEC_PT8211_DEFAULT_HANDLE
|
||||
#endif
|
||||
|
||||
static const char *TAG = "AUDIO_BOARD";
|
||||
|
||||
@@ -271,7 +271,8 @@ esp_err_t ma_write(uint8_t i2c_addr, uint8_t prot, uint16_t address,
|
||||
i2c_master_write_byte(cmd, wbuf[i], ack);
|
||||
}
|
||||
i2c_master_stop(cmd);
|
||||
int ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
|
||||
int ret =
|
||||
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret == ESP_FAIL) {
|
||||
return ret;
|
||||
@@ -294,7 +295,7 @@ esp_err_t ma_write_byte(uint8_t i2c_addr, uint8_t prot, uint16_t address,
|
||||
}
|
||||
i2c_master_write_byte(cmd, value, ACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
|
||||
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret == ESP_FAIL) {
|
||||
printf("ESP_I2C_WRITE ERROR : %d\n", ret);
|
||||
@@ -326,7 +327,7 @@ esp_err_t ma_read(uint8_t i2c_addr, uint8_t prot, uint16_t address,
|
||||
// { i2c_master_read_byte(cmd, rbuf++, ACK_VAL); }
|
||||
i2c_master_read_byte(cmd, rbuf + n - 1, NACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 100 / portTICK_RATE_MS);
|
||||
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 100 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret == ESP_FAIL) {
|
||||
printf("i2c Error read - readback\n");
|
||||
@@ -353,7 +354,7 @@ uint8_t ma_read_byte(uint8_t i2c_addr, uint8_t prot, uint16_t address) {
|
||||
i2c_master_read_byte(cmd, &value, NACK_VAL);
|
||||
|
||||
i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
|
||||
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret == ESP_FAIL) {
|
||||
printf("i2c Error read - readback\n");
|
||||
|
||||
@@ -283,7 +283,8 @@ esp_err_t ma_write(uint8_t i2c_addr, uint8_t prot, uint16_t address,
|
||||
i2c_master_write_byte(cmd, wbuf[i], ack);
|
||||
}
|
||||
i2c_master_stop(cmd);
|
||||
int ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
|
||||
int ret =
|
||||
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret == ESP_FAIL) {
|
||||
return ret;
|
||||
@@ -306,7 +307,7 @@ esp_err_t ma_write_byte(uint8_t i2c_addr, uint8_t prot, uint16_t address,
|
||||
}
|
||||
i2c_master_write_byte(cmd, value, ACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
|
||||
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret == ESP_FAIL) {
|
||||
printf("ESP_I2C_WRITE ERROR : %d\n", ret);
|
||||
@@ -338,7 +339,7 @@ esp_err_t ma_read(uint8_t i2c_addr, uint8_t prot, uint16_t address,
|
||||
// { i2c_master_read_byte(cmd, rbuf++, ACK_VAL); }
|
||||
i2c_master_read_byte(cmd, rbuf + n - 1, NACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 100 / portTICK_RATE_MS);
|
||||
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 100 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret == ESP_FAIL) {
|
||||
printf("i2c Error read - readback\n");
|
||||
@@ -365,7 +366,7 @@ uint8_t ma_read_byte(uint8_t i2c_addr, uint8_t prot, uint16_t address) {
|
||||
i2c_master_read_byte(cmd, &value, NACK_VAL);
|
||||
|
||||
i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
|
||||
ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
if (ret == ESP_FAIL) {
|
||||
printf("i2c Error read - readback\n");
|
||||
|
||||
@@ -106,9 +106,9 @@ io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
gpio_config(&io_conf);
|
||||
gpio_set_level(PCM51XX_RST_GPIO, 0);
|
||||
vTaskDelay(20 / portTICK_RATE_MS);
|
||||
vTaskDelay(20 / portTICK_PERIOD_MS);
|
||||
gpio_set_level(PCM51XX_RST_GPIO, 1);
|
||||
vTaskDelay(200 / portTICK_RATE_MS);
|
||||
vTaskDelay(200 / portTICK_PERIOD_MS);
|
||||
*/
|
||||
|
||||
ret = get_i2c_pins(I2C_NUM_0, &i2c_cfg);
|
||||
|
||||
49
components/custom_board/pt8211/include/pt8211.h
Normal file
49
components/custom_board/pt8211/include/pt8211.h
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Princeton Technology PT8211 audio hal
|
||||
*/
|
||||
|
||||
#ifndef _PT8211_H_
|
||||
#define _PT8211_H_
|
||||
|
||||
#include "audio_hal.h"
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Initialize PT8211 codec chip
|
||||
*/
|
||||
esp_err_t pt8211_init(audio_hal_codec_config_t *codec_cfg);
|
||||
|
||||
/**
|
||||
* Deinitialize PT8211 codec chip
|
||||
*/
|
||||
esp_err_t pt8211_deinit(void);
|
||||
|
||||
/**
|
||||
* Set volume - NOT AVAILABLE
|
||||
*/
|
||||
esp_err_t pt8211_set_volume(int vol);
|
||||
|
||||
/**
|
||||
* Get volume - NOT AVAILABLE
|
||||
*/
|
||||
esp_err_t pt8211_get_volume(int *value);
|
||||
|
||||
/**
|
||||
* Set PT8211 mute or not
|
||||
*/
|
||||
esp_err_t pt8211_set_mute(bool enable);
|
||||
|
||||
/**
|
||||
* Get PT8211 mute status - NOT IMPLEMENTED
|
||||
*/
|
||||
esp_err_t pt8211_get_mute(bool *enabled);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
90
components/custom_board/pt8211/pt8211.c
Normal file
90
components/custom_board/pt8211/pt8211.c
Normal file
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Princeton Technology PT8211 audio hal
|
||||
*
|
||||
* Mostly stubs (no I2C or volume control)
|
||||
* Configuration of mute/unmute gpio in init (for external amplifier)
|
||||
*/
|
||||
|
||||
#include "pt8211.h"
|
||||
|
||||
#include <driver/gpio.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#ifndef CONFIG_PT8211_MUTE_ACTIVE_LOW
|
||||
#define CONFIG_PT8211_MUTE_ACTIVE_LOW 0
|
||||
#endif
|
||||
|
||||
static const char *TAG = "PT8211";
|
||||
|
||||
esp_err_t pt8211_ctrl(audio_hal_codec_mode_t mode, audio_hal_ctrl_t ctrl_state);
|
||||
esp_err_t pt8211_config_iface(audio_hal_codec_mode_t mode,
|
||||
audio_hal_codec_i2s_iface_t *iface);
|
||||
|
||||
audio_hal_func_t AUDIO_CODEC_PT8211_DEFAULT_HANDLE = {
|
||||
.audio_codec_initialize = pt8211_init,
|
||||
.audio_codec_deinitialize = pt8211_deinit,
|
||||
.audio_codec_ctrl = pt8211_ctrl,
|
||||
.audio_codec_config_iface = pt8211_config_iface,
|
||||
.audio_codec_set_mute = pt8211_set_mute,
|
||||
.audio_codec_set_volume = pt8211_set_volume,
|
||||
.audio_codec_get_volume = pt8211_get_volume,
|
||||
.audio_hal_lock = NULL,
|
||||
.handle = NULL,
|
||||
};
|
||||
|
||||
esp_err_t pt8211_init(audio_hal_codec_config_t *codec_cfg) {
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
#if CONFIG_PT8211_MUTE_PIN != -1
|
||||
gpio_config_t io_conf;
|
||||
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = (1ULL << CONFIG_PT8211_MUTE_PIN);
|
||||
io_conf.pull_down_en = 0;
|
||||
io_conf.pull_up_en = 0;
|
||||
|
||||
ret = gpio_config(&io_conf);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Mute gpio config failed for pin %d", CONFIG_PT8211_MUTE_PIN);
|
||||
} else {
|
||||
gpio_set_level(CONFIG_PT8211_MUTE_PIN, 0);
|
||||
ESP_LOGD(TAG, "Setup mute output %d\n", CONFIG_PT8211_MUTE_PIN);
|
||||
}
|
||||
#else
|
||||
ESP_LOGD(TAG, "Mute gpio not specified\n");
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t pt8211_set_volume(int vol) { return ESP_OK; }
|
||||
|
||||
esp_err_t pt8211_get_volume(int *value) { return ESP_OK; }
|
||||
|
||||
esp_err_t pt8211_set_mute(bool enable) {
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
#if CONFIG_PT8211_MUTE_PIN != -1
|
||||
ret = gpio_set_level(CONFIG_PT8211_MUTE_PIN,
|
||||
enable ^ CONFIG_PT8211_MUTE_ACTIVE_LOW);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t pt8211_get_mute(bool *enabled) { return ESP_OK; }
|
||||
|
||||
esp_err_t pt8211_deinit(void) { return gpio_reset_pin(CONFIG_PT8211_MUTE_PIN); }
|
||||
|
||||
esp_err_t pt8211_ctrl(audio_hal_codec_mode_t mode,
|
||||
audio_hal_ctrl_t ctrl_state) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pt8211_config_iface(audio_hal_codec_mode_t mode,
|
||||
audio_hal_codec_i2s_iface_t *iface) {
|
||||
return ESP_OK;
|
||||
}
|
||||
146
components/custom_board/tas5805m/include/tas5805m.h
Normal file
146
components/custom_board/tas5805m/include/tas5805m.h
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2020 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in
|
||||
* which case, it is free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TAS5805M_H_
|
||||
#define _TAS5805M_H_
|
||||
|
||||
#include "audio_hal.h"
|
||||
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "board.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
#define I2C_MASTER_FREQ_HZ 400000 /*!< I2C master clock frequency */
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master doesn't need buffer */
|
||||
#define I2C_MASTER_TIMEOUT_MS 1000
|
||||
|
||||
/* Represented in % */
|
||||
#define TAS5805M_VOLUME_MIN 0
|
||||
#define TAS5805M_VOLUME_MAX 100
|
||||
|
||||
#define TAS5805M_VOLUME_MUTE 255
|
||||
/* See here for the original Implementation : audio_hal/driver/tas5805m */
|
||||
/* Its not from me it was developed by Espressif */
|
||||
/* Volume steps tas5805m_volume[0] => 255 which means mute */
|
||||
static const uint8_t tas5805m_volume[]
|
||||
= { 0xff, 0x9f, 0x8f, 0x7f, 0x6f, 0x5f, 0x5c, 0x5a, 0x58, 0x54, 0x50,
|
||||
0x4c, 0x4a, 0x48, 0x44, 0x40, 0x3d, 0x3b, 0x39, 0x37, 0x35 };
|
||||
|
||||
int8_t currentVolume = 0; // Last Volume gets updated after a change or before a mute
|
||||
/**
|
||||
* @brief Initialize TAS5805 codec chip
|
||||
*
|
||||
* @param cfg configuration of TAS5805
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_FAIL
|
||||
*/
|
||||
esp_err_t tas5805m_init ();
|
||||
|
||||
/**
|
||||
* @brief Deinitialize TAS5805 codec chip
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_FAIL
|
||||
*/
|
||||
esp_err_t tas5805m_deinit (void);
|
||||
|
||||
/**
|
||||
* @brief Set voice volume
|
||||
*
|
||||
* @param volume: voice volume (0~100)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_FAIL
|
||||
*/
|
||||
esp_err_t tas5805m_set_volume (int vol);
|
||||
|
||||
/**
|
||||
* @brief Get voice volume
|
||||
*
|
||||
* @param[out] *volume: voice volume (0~100)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK
|
||||
* - ESP_FAIL
|
||||
*/
|
||||
esp_err_t tas5805m_get_volume(int *vol);
|
||||
|
||||
/**
|
||||
* @brief Set TAS5805 mute or not
|
||||
* Continuously call should have an interval time determined by
|
||||
* tas5805m_set_mute_fade()
|
||||
*
|
||||
* @param enable enable(1) or disable(0)
|
||||
*
|
||||
* @return
|
||||
* - ESP_FAIL Parameter error
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t tas5805m_set_mute (bool enable);
|
||||
|
||||
/**
|
||||
* @brief Mute TAS5805M
|
||||
*
|
||||
* @param value Time for mute with millisecond.
|
||||
* @return
|
||||
* - ESP_FAIL Parameter error
|
||||
* - ESP_OK Success
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get TAS5805 mute status
|
||||
*
|
||||
* @return
|
||||
* - ESP_FAIL Parameter error
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t tas5805m_get_mute (bool *enabled);
|
||||
|
||||
esp_err_t tas5805m_ctrl(audio_hal_codec_mode_t mode,
|
||||
audio_hal_ctrl_t ctrl_state);
|
||||
|
||||
|
||||
esp_err_t tas5805m_config_iface(audio_hal_codec_mode_t mode,
|
||||
audio_hal_codec_i2s_iface_t *iface);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
100
components/custom_board/tas5805m/include/tas5805m_reg_cfg.h
Normal file
100
components/custom_board/tas5805m/include/tas5805m_reg_cfg.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2020 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in
|
||||
* which case, it is free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TAS5805M_REG_CFG_
|
||||
#define _TAS5805M_REG_CFG_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
/* Register Naming*/
|
||||
#define I2C_MASTER_NUM I2C_NUM_0 /*!< I2C port number for master dev */
|
||||
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
|
||||
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
|
||||
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
||||
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
|
||||
#define ACK_VAL I2C_MASTER_ACK /*!< I2C ack value */
|
||||
#define NACK_VAL I2C_MASTER_NACK /*!< I2C nack value */
|
||||
|
||||
#define I2C_TAS5805M_MASTER_NUM I2C_MASTER_NUM /*!< I2C port number for master dev */
|
||||
|
||||
#define TAS5805M_ADDRESS 0x2D /*!< 7-bit address with a 15k pull up resistor */
|
||||
|
||||
|
||||
#ifdef PIN_DAC_PWDN
|
||||
#define TAS5805M_GPIO_PDN PIN_DAC_PWDN
|
||||
#else
|
||||
#define TAS5805M_GPIO_PDN GPIO_NUM_33 /*!< GPIO used for !PDN pin */
|
||||
#endif
|
||||
|
||||
#define TAS5805M_GPIO_PDN_MASK ((1ULL << TAS5805M_GPIO_PDN))
|
||||
|
||||
#define TAS5805M_RESET_CTRL_REGISTER 0x01
|
||||
#define TAS5805M_DEVICE_CTRL_1_REGISTER 0x02
|
||||
#define TAS5805M_DEVICE_CTRL_2_REGISTER 0x03
|
||||
#define TAS5805M_I2C_PAGE_AUTO_INC_REGISTER 0x0f
|
||||
#define TAS5805M_SIG_CH_CTRL_REGISTER 0x28
|
||||
#define TAS5805M_CLOCK_DET_CTRL_REGISTER 0x29
|
||||
#define TAS5805M_SDOUT_SEL_REGISTER 0x30
|
||||
#define TAS5805M_I2S_CTRL_REGISTER 0x31
|
||||
#define TAS5805M_SAP_CTRL1_REGISTER 0x33
|
||||
#define TAS5805M_SAP_CTRL2_REGISTER 0x34
|
||||
#define TAS5805M_SAP_CTRL3_REGISTER 0x35
|
||||
#define TAS5805M_FS_MON_REGISTER 0x37
|
||||
#define TAS5805M_BCK_MON_REGISTER 0x38
|
||||
#define TAS5805M_CLKDET_STATUS_REGISTER 0x39
|
||||
#define TAS5805M_CHANNEL_FORCE_HIZ_REGISTER 0x40
|
||||
#define TAS5805M_DIG_VOL_CTRL_REGISTER 0x4c
|
||||
#define TAS5805M_DIG_VOL_CTRL2_REGISTER 0x4e
|
||||
#define TAS5805M_DIG_VOL_CTRL3_REGISTER 0x4f
|
||||
#define TAS5805M_AUTO_MUTE_CTRL_REGISTER 0x50
|
||||
#define TAS5805M_AUTO_MUTE_TIME_REGISTER 0x51
|
||||
#define TAS5805M_ANA_CTRL_REGISTER 0x53
|
||||
#define TAS5805M_AGAIN_REGISTER 0x54
|
||||
#define TAS5805M_BQ_WR_CTRL1_REGISTER 0x5c
|
||||
#define TAS5805M_DAC_CTRL_REGISTER 0x5d
|
||||
#define TAS5805M_ADR_PIN_CTRL_REGISTER 0x60
|
||||
#define TAS5805M_ADR_PIN_CONFIG_REGISTER 0x61
|
||||
#define TAS5805M_DSP_MISC_REGISTER 0x66
|
||||
#define TAS5805M_DIE_ID_REGISTER 0x67
|
||||
#define TAS5805M_POWER_STATE_REGISTER 0x68
|
||||
#define TAS5805M_AUTOMUTE_STATE_REGISTER 0x69
|
||||
#define TAS5805M_PHASE_CTRL_REGISTER 0x6a
|
||||
#define TAS5805M_SS_CTRL0_REGISTER 0x6b
|
||||
#define TAS5805M_SS_CTRL1_REGISTER 0x6c
|
||||
#define TAS5805M_SS_CTRL2_REGISTER 0x6d
|
||||
#define TAS5805M_SS_CTRL3_REGISTER 0x6e
|
||||
#define TAS5805M_SS_CTRL4_REGISTER 0x6f
|
||||
#define TAS5805M_CHAN_FAULT_REGISTER 0x70
|
||||
#define TAS5805M_GLOBAL_FAULT1_REGISTER 0x71
|
||||
#define TAS5805M_GLOBAL_FAULT2_REGISTER 0x72
|
||||
#define TAS5805M_OT_WARNING_REGISTER 0x73
|
||||
#define TAS5805M_PIN_CONTROL1_REGISTER 0x74
|
||||
#define TAS5805M_PIN_CONTROL2_REGISTER 0x75
|
||||
#define TAS5805M_MISC_CONTROL_REGISTER 0x76
|
||||
#define TAS5805M_FAULT_CLEAR_REGISTER 0x78
|
||||
#endif
|
||||
260
components/custom_board/tas5805m/tas5805m.c
Normal file
260
components/custom_board/tas5805m/tas5805m.c
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* ESPRESSIF MIT License
|
||||
*
|
||||
* Copyright (c) 2020 <ESPRESSIF SYSTEMS (SHANGHAI) CO., LTD>
|
||||
*
|
||||
* Permission is hereby granted for use on all ESPRESSIF SYSTEMS products, in
|
||||
* which case, it is free of charge, to any person obtaining a copy of this
|
||||
* software and associated documentation files (the "Software"), to deal in the
|
||||
* Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
* IN THE SOFTWARE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "tas5805m.h"
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "i2c_bus.h"
|
||||
#include "tas5805m_reg_cfg.h"
|
||||
|
||||
static const char *TAG = "TAS5805M";
|
||||
|
||||
/* Default I2C config */
|
||||
|
||||
static i2c_config_t i2c_cfg = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = I2C_MASTER_FREQ_HZ,
|
||||
};
|
||||
|
||||
/*
|
||||
* Operate fuction of PA
|
||||
*/
|
||||
audio_hal_func_t AUDIO_CODEC_TAS5805M_DEFAULT_HANDLE = {
|
||||
.audio_codec_initialize = tas5805m_init,
|
||||
.audio_codec_deinitialize = tas5805m_deinit,
|
||||
.audio_codec_ctrl = tas5805m_ctrl,
|
||||
.audio_codec_config_iface = tas5805m_config_iface,
|
||||
.audio_codec_set_mute = tas5805m_set_mute,
|
||||
.audio_codec_set_volume = tas5805m_set_volume,
|
||||
.audio_codec_get_volume = tas5805m_get_volume,
|
||||
.audio_hal_lock = NULL,
|
||||
.handle = NULL,
|
||||
};
|
||||
|
||||
/* Init the I2C Driver */
|
||||
|
||||
void i2c_master_init() {
|
||||
int i2c_master_port = I2C_MASTER_NUM;
|
||||
|
||||
ESP_ERROR_CHECK(get_i2c_pins(I2C_NUM_0, &i2c_cfg));
|
||||
|
||||
ESP_ERROR_CHECK(i2c_param_config(i2c_master_port, &i2c_cfg));
|
||||
|
||||
ESP_ERROR_CHECK(i2c_driver_install(i2c_master_port, i2c_cfg.mode,
|
||||
I2C_MASTER_RX_BUF_DISABLE,
|
||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||
}
|
||||
|
||||
/* Helper Functions */
|
||||
|
||||
// Reading of TAS5805M-Register
|
||||
|
||||
esp_err_t tas5805m_read_byte(uint8_t register_name, uint8_t *data) {
|
||||
int ret;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, TAS5805M_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, register_name, ACK_CHECK_EN);
|
||||
i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(I2C_TAS5805M_MASTER_NUM, cmd,
|
||||
1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "I2C ERROR");
|
||||
}
|
||||
|
||||
vTaskDelay(1 / portTICK_PERIOD_MS);
|
||||
cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, TAS5805M_ADDRESS << 1 | READ_BIT, ACK_CHECK_EN);
|
||||
i2c_master_read_byte(cmd, data, NACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
ret = i2c_master_cmd_begin(I2C_TAS5805M_MASTER_NUM, cmd,
|
||||
1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Writing of TAS5805M-Register
|
||||
|
||||
esp_err_t tas5805m_write_byte(uint8_t register_name, uint8_t value) {
|
||||
int ret = 0;
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, TAS5805M_ADDRESS << 1 | WRITE_BIT, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, register_name, ACK_CHECK_EN);
|
||||
i2c_master_write_byte(cmd, value, ACK_CHECK_EN);
|
||||
i2c_master_stop(cmd);
|
||||
|
||||
ret = i2c_master_cmd_begin(I2C_TAS5805M_MASTER_NUM, cmd,
|
||||
1000 / portTICK_PERIOD_MS);
|
||||
|
||||
// Check if ret is OK
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Fehler bei der I2C-Übertragung: %s", esp_err_to_name(ret));
|
||||
}
|
||||
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Inits the TAS5805M change Settings in Menuconfig to enable Bridge-Mode
|
||||
|
||||
esp_err_t tas5805m_init() {
|
||||
int ret = 0;
|
||||
// Init the I2C-Driver
|
||||
i2c_master_init();
|
||||
/* Register the PDN pin as output and write 1 to enable the TAS chip */
|
||||
/* TAS5805M.INIT() */
|
||||
gpio_config_t io_conf;
|
||||
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||
io_conf.pin_bit_mask = TAS5805M_GPIO_PDN_MASK;
|
||||
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||
ESP_LOGW(TAG, "Power down pin: %d", TAS5805M_GPIO_PDN);
|
||||
gpio_config(&io_conf);
|
||||
gpio_set_level(TAS5805M_GPIO_PDN, 0);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
gpio_set_level(TAS5805M_GPIO_PDN, 1);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
|
||||
/* TAS5805M.Begin()*/
|
||||
|
||||
ESP_LOGW(TAG, "Setting to HI Z");
|
||||
|
||||
ESP_ERROR_CHECK(tas5805m_write_byte(TAS5805M_DEVICE_CTRL_2_REGISTER, 0x02));
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "TAS5805M_DEVICE_CTRL_2_REGISTER, 0x02 FAILED!!!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ESP_LOGW(TAG, "Setting to PLAY");
|
||||
|
||||
ret = tas5805m_write_byte(TAS5805M_DEVICE_CTRL_2_REGISTER, 0x03);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGW(TAG, "TAS5805M_DEVICE_CTRL_2_REGISTER, 0x03 FAILED!!");
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Check if Bridge-Mode is enabled
|
||||
#ifdef CONFIG_DAC_BRIDGE_MODE
|
||||
uint8_t value = 0;
|
||||
ret = tas5805m_read_byte(TAS5805M_DEVICE_CTRL_1_REGISTER, &value);
|
||||
if (ret != ESP_OK) return ret;
|
||||
value = 0b100;
|
||||
|
||||
ret = tas5805m_write_byte(TAS5805M_DEVICE_CTRL_1_REGISTER, value);
|
||||
if (ret != ESP_OK) return ret;
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Setting the Volume
|
||||
|
||||
esp_err_t tas5805m_set_volume(int vol) {
|
||||
int vol_idx = 0; // Temp-Variable
|
||||
|
||||
/* Checking if Volume is bigger or smaller than the max values */
|
||||
if (vol < TAS5805M_VOLUME_MIN) {
|
||||
vol = TAS5805M_VOLUME_MIN;
|
||||
}
|
||||
if (vol > TAS5805M_VOLUME_MAX) {
|
||||
vol = TAS5805M_VOLUME_MAX;
|
||||
}
|
||||
/* Mapping the Values from 0-100 to 254-0 */
|
||||
vol_idx = vol / 5;
|
||||
/* Updating the global volume Variable */
|
||||
currentVolume = vol_idx;
|
||||
/* Writing the Volume to the Register*/
|
||||
return tas5805m_write_byte(TAS5805M_DIG_VOL_CTRL_REGISTER,
|
||||
tas5805m_volume[vol_idx]);
|
||||
}
|
||||
|
||||
esp_err_t tas5805m_get_volume(int *vol) {
|
||||
esp_err_t ret = ESP_OK;
|
||||
uint8_t rxbuf = 0;
|
||||
ret = tas5805m_read_byte(TAS5805M_DIG_VOL_CTRL_REGISTER, &rxbuf);
|
||||
int i;
|
||||
for (i = 0; i < sizeof(tas5805m_volume); i++) {
|
||||
if (rxbuf >= tas5805m_volume[i]) break;
|
||||
}
|
||||
/* Updating the global volume Variable */
|
||||
currentVolume = i;
|
||||
ESP_LOGI(TAG, "Volume is %d", i * 5);
|
||||
*vol = 5 * i; // Converting it to percent
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t tas5805m_deinit(void) {
|
||||
// TODO
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t tas5805m_set_mute(bool enable) {
|
||||
if (enable == true) {
|
||||
// Set the Volume to 255 to enable the MUTE
|
||||
return tas5805m_write_byte(TAS5805M_DIG_VOL_CTRL_REGISTER,
|
||||
TAS5805M_VOLUME_MUTE);
|
||||
} else {
|
||||
return tas5805m_write_byte(
|
||||
TAS5805M_DIG_VOL_CTRL_REGISTER,
|
||||
tas5805m_volume[currentVolume]); // Restore Volume to its old value
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t tas5805m_get_mute(bool *enabled) {
|
||||
int currentVolume;
|
||||
if (tas5805m_get_volume(¤tVolume) != ESP_OK) {
|
||||
ESP_LOGW(TAG, "Cant get volume in get-Mute-Function");
|
||||
}
|
||||
if (currentVolume == TAS5805M_VOLUME_MUTE) {
|
||||
*enabled = true;
|
||||
} else {
|
||||
*enabled = false;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t tas5805m_ctrl(audio_hal_codec_mode_t mode,
|
||||
audio_hal_ctrl_t ctrl_state) {
|
||||
// TODO
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t tas5805m_config_iface(audio_hal_codec_mode_t mode,
|
||||
audio_hal_codec_i2s_iface_t *iface) {
|
||||
// TODO
|
||||
return ESP_OK;
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
#ifndef _DSP_PROCESSOR_H_
|
||||
#define _DSP_PROCESSOR_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "esp_err.h"
|
||||
|
||||
typedef enum dspFlows {
|
||||
@@ -64,4 +68,8 @@ int dsp_processor_worker(char *audio, size_t chunk_size, uint32_t samplerate);
|
||||
esp_err_t dsp_processor_update_filter_params(filterParams_t *params);
|
||||
void dsp_processor_set_volome(double volume);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DSP_PROCESSOR_H_ */
|
||||
|
||||
@@ -33,7 +33,6 @@
|
||||
#include "audio_mutex.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/projdefs.h"
|
||||
|
||||
#define ESP_INTR_FLG_DEFAULT (0)
|
||||
#define ESP_I2C_MASTER_BUF_LEN (0)
|
||||
@@ -117,7 +116,7 @@ esp_err_t i2c_bus_write_bytes(i2c_bus_handle_t bus, int addr, uint8_t *reg,
|
||||
ret |= i2c_master_write(cmd, reg, regLen, I2C_ACK_CHECK_EN);
|
||||
ret |= i2c_master_write(cmd, data, datalen, I2C_ACK_CHECK_EN);
|
||||
ret |= i2c_master_stop(cmd);
|
||||
ret |= i2c_master_cmd_begin(p_bus->i2c_port, cmd, pdMS_TO_TICKS(1000));
|
||||
ret |= i2c_master_cmd_begin(p_bus->i2c_port, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
mutex_unlock(p_bus->bus_lock);
|
||||
I2C_BUS_CHECK(ret == 0, "I2C Bus WriteReg Error", ESP_FAIL);
|
||||
@@ -137,7 +136,7 @@ esp_err_t i2c_bus_write_data(i2c_bus_handle_t bus, int addr, uint8_t *data,
|
||||
ret |= i2c_master_write_byte(cmd, addr, 1);
|
||||
ret |= i2c_master_write(cmd, data, datalen, I2C_ACK_CHECK_EN);
|
||||
ret |= i2c_master_stop(cmd);
|
||||
ret |= i2c_master_cmd_begin(p_bus->i2c_port, cmd, pdMS_TO_TICKS(1000));
|
||||
ret |= i2c_master_cmd_begin(p_bus->i2c_port, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
mutex_unlock(p_bus->bus_lock);
|
||||
I2C_BUS_CHECK(ret == 0, "I2C Bus WriteReg Error", ESP_FAIL);
|
||||
@@ -159,7 +158,7 @@ esp_err_t i2c_bus_read_bytes(i2c_bus_handle_t bus, int addr, uint8_t *reg,
|
||||
ret |= i2c_master_write_byte(cmd, addr, I2C_ACK_CHECK_EN);
|
||||
ret |= i2c_master_write(cmd, reg, reglen, I2C_ACK_CHECK_EN);
|
||||
ret |= i2c_master_stop(cmd);
|
||||
ret |= i2c_master_cmd_begin(p_bus->i2c_port, cmd, pdMS_TO_TICKS(1000));
|
||||
ret |= i2c_master_cmd_begin(p_bus->i2c_port, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
cmd = i2c_cmd_link_create();
|
||||
@@ -172,7 +171,7 @@ esp_err_t i2c_bus_read_bytes(i2c_bus_handle_t bus, int addr, uint8_t *reg,
|
||||
ret |= i2c_master_read_byte(cmd, &outdata[datalen - 1], 1);
|
||||
|
||||
ret |= i2c_master_stop(cmd);
|
||||
ret |= i2c_master_cmd_begin(p_bus->i2c_port, cmd, pdMS_TO_TICKS(1000));
|
||||
ret |= i2c_master_cmd_begin(p_bus->i2c_port, cmd, 1000 / portTICK_PERIOD_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
|
||||
mutex_unlock(p_bus->bus_lock);
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
static const char *TAG = "ESP_PERIPH";
|
||||
|
||||
#define DEFAULT_ESP_PERIPH_WAIT_TICK (10 / portTICK_RATE_MS)
|
||||
#define DEFAULT_ESP_PERIPH_WAIT_TICK (10 / portTICK_PERIOD_MS)
|
||||
|
||||
struct esp_periph {
|
||||
char *tag;
|
||||
@@ -57,7 +57,7 @@ struct esp_periph {
|
||||
|
||||
typedef struct esp_periph_sets {
|
||||
EventGroupHandle_t state_event_bits;
|
||||
xSemaphoreHandle lock;
|
||||
SemaphoreHandle_t lock;
|
||||
int task_stack;
|
||||
int task_prio;
|
||||
int task_core;
|
||||
@@ -93,7 +93,7 @@ esp_err_t esp_periph_set_change_waiting_time(
|
||||
esp_periph_set_handle_t periph_set_handle, int time_ms) {
|
||||
audio_event_iface_set_cmd_waiting_timeout(
|
||||
esp_periph_set_get_event_iface(periph_set_handle),
|
||||
time_ms / portTICK_RATE_MS);
|
||||
time_ms / portTICK_PERIOD_MS);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -106,7 +106,7 @@ static esp_err_t _button_init(esp_periph_handle_t self) {
|
||||
};
|
||||
periph_btn->btn = button_init(&btn_config);
|
||||
|
||||
esp_periph_start_timer(self, 50 / portTICK_RATE_MS, button_timer_handler);
|
||||
esp_periph_start_timer(self, 50 / portTICK_PERIOD_MS, button_timer_handler);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@@ -218,7 +218,7 @@ static void _console_task(void *pv) {
|
||||
printf("\r\n%s ", prompt_string);
|
||||
while (console->run) {
|
||||
if (console_get_line(console, console->buffer_size,
|
||||
10 / portTICK_RATE_MS)) {
|
||||
10 / portTICK_PERIOD_MS)) {
|
||||
if (console->total_bytes) {
|
||||
ESP_LOGD(TAG, "Read line: %s", console->buffer);
|
||||
}
|
||||
|
||||
@@ -234,7 +234,7 @@ esp_err_t periph_led_blink(esp_periph_handle_t periph, int gpio_num,
|
||||
}
|
||||
ch->stop = false;
|
||||
ch->level = level;
|
||||
esp_periph_start_timer(periph, portTICK_RATE_MS, led_timer_handler);
|
||||
esp_periph_start_timer(periph, portTICK_PERIOD_MS, led_timer_handler);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ static esp_err_t _sdcard_init(esp_periph_handle_t self) {
|
||||
} else {
|
||||
ESP_LOGE(TAG, "no sdcard detect");
|
||||
}
|
||||
esp_periph_start_timer(self, 1000 / portTICK_RATE_MS, sdcard_timer_handler);
|
||||
esp_periph_start_timer(self, 1000 / portTICK_PERIOD_MS, sdcard_timer_handler);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
@@ -346,9 +346,9 @@ static void _wifi_event_callback(void *arg, esp_event_base_t event_base,
|
||||
if (periph_wifi->disable_auto_reconnect) {
|
||||
return;
|
||||
}
|
||||
esp_periph_start_timer(self,
|
||||
periph_wifi->reconnect_timeout_ms / portTICK_RATE_MS,
|
||||
wifi_reconnect_timer);
|
||||
esp_periph_start_timer(
|
||||
self, periph_wifi->reconnect_timeout_ms / portTICK_PERIOD_MS,
|
||||
wifi_reconnect_timer);
|
||||
|
||||
} else {
|
||||
ESP_LOGW(TAG, "WiFi Event cb, Unhandle event_base:%s, event_id:%d",
|
||||
@@ -395,10 +395,12 @@ static esp_err_t _wifi_event_callback(void *ctx, system_event_t *event) {
|
||||
break;
|
||||
}
|
||||
esp_periph_start_timer(
|
||||
self, periph_wifi->reconnect_timeout_ms / portTICK_RATE_MS,
|
||||
self, periph_wifi->reconnect_timeout_ms / portTICK_PERIOD_MS,
|
||||
wifi_reconnect_timer);
|
||||
break;
|
||||
default:
|
||||
ESP_LOGW(TAG, "WiFi Event cb, Unhandled event_id: 0x%08X",
|
||||
event->event_id);
|
||||
break;
|
||||
}
|
||||
return ESP_OK;
|
||||
|
||||
@@ -90,7 +90,7 @@ typedef struct periph_ws2812 {
|
||||
periph_rgb_value *color;
|
||||
uint32_t led_num;
|
||||
TimerHandle_t timer;
|
||||
xSemaphoreHandle sem;
|
||||
SemaphoreHandle_t sem;
|
||||
intr_handle_t rmt_intr_handle;
|
||||
periph_ws2812_state_t *state;
|
||||
periph_ws2812_process_t process;
|
||||
@@ -404,7 +404,7 @@ esp_err_t periph_ws2812_control(esp_periph_handle_t periph,
|
||||
periph_ws2812->state[i].mode = control_cfg[i].mode;
|
||||
}
|
||||
|
||||
esp_periph_start_timer(periph, INTERVAL_TIME_MS / portTICK_RATE_MS,
|
||||
esp_periph_start_timer(periph, INTERVAL_TIME_MS / portTICK_PERIOD_MS,
|
||||
ws2812_timer_handler);
|
||||
|
||||
return ESP_OK;
|
||||
|
||||
@@ -214,7 +214,7 @@ static void periph_console_test(void) {
|
||||
TEST_ASSERT_FALSE(esp_periph_start(set, console_handle));
|
||||
|
||||
while (task_flag) {
|
||||
vTaskDelay(10 / portTICK_RATE_MS);
|
||||
vTaskDelay(10 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Quit test, release all resources");
|
||||
@@ -295,7 +295,7 @@ static void periph_is31fl3216_test(void) {
|
||||
periph_is31fl3216_set_state(is31fl3216_handle, IS31FL3216_STATE_SHIFT));
|
||||
ESP_LOGI(TAG, "Start testing for 5 seconds...");
|
||||
|
||||
vTaskDelay(5000 / portTICK_RATE_MS);
|
||||
vTaskDelay(5000 / portTICK_PERIOD_MS);
|
||||
|
||||
ESP_LOGI(TAG, "Quit test, release all resources");
|
||||
TEST_ASSERT_FALSE(esp_periph_set_stop_all(set));
|
||||
@@ -326,11 +326,11 @@ static void periph_led_test(void) {
|
||||
false, 4, 0));
|
||||
|
||||
ESP_LOGI(TAG, "running...");
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGI(TAG, "STOP BLUE LED");
|
||||
TEST_ASSERT_FALSE(periph_led_stop(led_handle, get_blue_led_gpio()));
|
||||
|
||||
vTaskDelay(1000 / portTICK_RATE_MS);
|
||||
vTaskDelay(1000 / portTICK_PERIOD_MS);
|
||||
ESP_LOGI(TAG, "Changing blink preset...");
|
||||
TEST_ASSERT_FALSE(periph_led_blink(led_handle, get_blue_led_gpio(), 500, 200,
|
||||
false, -1, 0));
|
||||
|
||||
@@ -1,8 +1,3 @@
|
||||
|
||||
#if(CONFIG_SNAPCLIENT_ENABLE_ETHERNET)
|
||||
idf_component_register(SRCS "eth_interface.c"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES driver esp_eth esp_netif)
|
||||
#else()
|
||||
# idf_component_register()
|
||||
#endif()
|
||||
idf_component_register(SRCS "eth_interface.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES driver esp_eth esp_netif)
|
||||
|
||||
@@ -1,51 +1,19 @@
|
||||
menu "Snapclient Ethernet Configuration"
|
||||
config SNAPCLIENT_ENABLE_ETHERNET
|
||||
bool "enable Ethernet"
|
||||
default n
|
||||
|
||||
orsource "$IDF_PATH/examples/common_components/env_caps/$IDF_TARGET/Kconfig.env_caps"
|
||||
|
||||
config SNAPCLIENT_USE_INTERNAL_ETHERNET
|
||||
depends on SOC_EMAC_SUPPORTED
|
||||
select ETH_USE_ESP32_EMAC
|
||||
default y
|
||||
bool "Internal EMAC"
|
||||
help
|
||||
Enable Ethernet interface
|
||||
|
||||
config SNAPCLIENT_USE_SPI_ETHERNET
|
||||
bool
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
|
||||
choice SNAPCLIENT_ETHERNET_TYPE
|
||||
prompt "Ethernet Type"
|
||||
default SNAPCLIENT_USE_INTERNAL_ETHERNET if IDF_TARGET_ESP32
|
||||
default SNAPCLIENT_USE_W5500
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
help
|
||||
Select which kind of Ethernet will be used in the example.
|
||||
|
||||
config SNAPCLIENT_USE_INTERNAL_ETHERNET
|
||||
depends on IDF_TARGET_ESP32
|
||||
select ETH_USE_ESP32_EMAC
|
||||
bool "Internal EMAC"
|
||||
help
|
||||
Select internal Ethernet MAC controller.
|
||||
|
||||
config SNAPCLIENT_USE_DM9051
|
||||
bool "DM9051 Module"
|
||||
select SNAPCLIENT_USE_SPI_ETHERNET
|
||||
select ETH_USE_SPI_ETHERNET
|
||||
select ETH_SPI_ETHERNET_DM9051
|
||||
help
|
||||
Select external SPI-Ethernet module (DM9051).
|
||||
|
||||
config SNAPCLIENT_USE_W5500
|
||||
bool "W5500 Module"
|
||||
select SNAPCLIENT_USE_SPI_ETHERNET
|
||||
select ETH_USE_SPI_ETHERNET
|
||||
select ETH_SPI_ETHERNET_W5500
|
||||
help
|
||||
Select external SPI-Ethernet module (W5500).
|
||||
endchoice # SNAPCLIENT_ETHERNET_TYPE
|
||||
Use internal Ethernet MAC controller.
|
||||
|
||||
if SNAPCLIENT_USE_INTERNAL_ETHERNET
|
||||
choice SNAPCLIENT_ETH_PHY_MODEL
|
||||
prompt "Ethernet PHY Device"
|
||||
default SNAPCLIENT_ETH_PHY_IP101
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
help
|
||||
Select the Ethernet PHY device to use in the example.
|
||||
|
||||
@@ -61,11 +29,18 @@ menu "Snapclient Ethernet Configuration"
|
||||
RTL8201F/SR8201F is a single port 10/100Mb Ethernet Transceiver with auto MDIX.
|
||||
Goto http://www.corechip-sz.com/productsview.asp?id=22 for more information about it.
|
||||
|
||||
config SNAPCLIENT_ETH_PHY_LAN8720
|
||||
bool "LAN8720"
|
||||
config SNAPCLIENT_ETH_PHY_LAN87XX
|
||||
bool "LAN87xx"
|
||||
help
|
||||
Below chips are supported:
|
||||
LAN8710A is a small footprint MII/RMII 10/100 Ethernet Transceiver with HP Auto-MDIX and
|
||||
flexPWR® Technology.
|
||||
LAN8720A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX Support.
|
||||
Goto https://www.microchip.com/LAN8720A for more information about it.
|
||||
LAN8740A/LAN8741A is a small footprint MII/RMII 10/100 Energy Efficient Ethernet Transceiver
|
||||
with HP Auto-MDIX and flexPWR® Technology.
|
||||
LAN8742A is a small footprint RMII 10/100 Ethernet Transceiver with HP Auto-MDIX and
|
||||
flexPWR® Technology.
|
||||
Goto https://www.microchip.com for more information about them.
|
||||
|
||||
config SNAPCLIENT_ETH_PHY_DP83848
|
||||
bool "DP83848"
|
||||
@@ -73,98 +48,202 @@ menu "Snapclient Ethernet Configuration"
|
||||
DP83848 is a single port 10/100Mb/s Ethernet Physical Layer Transceiver.
|
||||
Goto http://www.ti.com/product/DP83848J for more information about it.
|
||||
|
||||
config SNAPCLIENT_ETH_PHY_KSZ8041
|
||||
bool "KSZ8041"
|
||||
config SNAPCLIENT_ETH_PHY_KSZ80XX
|
||||
bool "KSZ80xx"
|
||||
help
|
||||
The KSZ8041 is a single supply 10Base-T/100Base-TX Physical Layer Transceiver.
|
||||
Goto https://www.microchip.com/wwwproducts/en/KSZ8041 for more information about it.
|
||||
With the KSZ80xx series, Microchip offers single-chip 10BASE-T/100BASE-TX
|
||||
Ethernet Physical Layer Tranceivers (PHY).
|
||||
The following chips are supported: KSZ8001, KSZ8021, KSZ8031, KSZ8041,
|
||||
KSZ8051, KSZ8061, KSZ8081, KSZ8091
|
||||
Goto https://www.microchip.com for more information about them.
|
||||
endchoice # SNAPCLIENT_ETH_PHY_MODEL
|
||||
|
||||
config SNAPCLIENT_ETH_MDC_GPIO
|
||||
int "SMI MDC GPIO number"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||
default 23
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
help
|
||||
Set the GPIO number used by SMI MDC.
|
||||
|
||||
config SNAPCLIENT_ETH_MDIO_GPIO
|
||||
int "SMI MDIO GPIO number"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||
default 18
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
help
|
||||
Set the GPIO number used by SMI MDIO.
|
||||
|
||||
config SNAPCLIENT_ETH_PHY_RST_GPIO
|
||||
int "PHY Reset GPIO number"
|
||||
range -1 ENV_GPIO_OUT_RANGE_MAX
|
||||
default 17
|
||||
help
|
||||
Set the GPIO number used to reset PHY chip.
|
||||
Set to -1 to disable PHY chip hardware reset.
|
||||
|
||||
config SNAPCLIENT_ETH_PHY_ADDR
|
||||
int "PHY Address"
|
||||
range 0 31
|
||||
default 0
|
||||
help
|
||||
Set PHY address according your board schematic.
|
||||
endif # SNAPCLIENT_USE_INTERNAL_ETHERNET
|
||||
|
||||
config SNAPCLIENT_USE_SPI_ETHERNET
|
||||
bool "SPI Ethernet"
|
||||
default n
|
||||
select ETH_USE_SPI_ETHERNET
|
||||
help
|
||||
Use external SPI-Ethernet module(s).
|
||||
|
||||
if SNAPCLIENT_USE_SPI_ETHERNET
|
||||
config SNAPCLIENT_SPI_ETHERNETS_NUM
|
||||
int "Number of SPI Ethernet modules to use at a time"
|
||||
range 1 2
|
||||
default 1
|
||||
help
|
||||
Set the number of SPI Ethernet modules you want to use at a time. Multiple SPI modules can be connected
|
||||
to one SPI interface and can be separately accessed based on state of associated Chip Select (CS).
|
||||
|
||||
choice SNAPCLIENT_ETHERNET_TYPE_SPI
|
||||
prompt "Ethernet SPI"
|
||||
default SNAPCLIENT_USE_W5500
|
||||
help
|
||||
Select which kind of Ethernet will be used in the example.
|
||||
|
||||
config SNAPCLIENT_USE_DM9051
|
||||
bool "DM9051 Module"
|
||||
select ETH_SPI_ETHERNET_DM9051
|
||||
help
|
||||
Select external SPI-Ethernet module (DM9051).
|
||||
|
||||
config SNAPCLIENT_USE_KSZ8851SNL
|
||||
bool "KSZ8851SNL Module"
|
||||
select ETH_SPI_ETHERNET_KSZ8851SNL
|
||||
help
|
||||
Select external SPI-Ethernet module (KSZ8851SNL).
|
||||
|
||||
config SNAPCLIENT_USE_W5500
|
||||
bool "W5500 Module"
|
||||
select ETH_SPI_ETHERNET_W5500
|
||||
help
|
||||
Select external SPI-Ethernet module (W5500).
|
||||
endchoice
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_HOST
|
||||
int "SPI Host Number"
|
||||
range 0 2
|
||||
default 1
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
help
|
||||
Set the SPI host used to communicate with the SPI Ethernet Controller.
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_SCLK_GPIO
|
||||
int "SPI SCLK GPIO number"
|
||||
range 0 33
|
||||
default 20
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||
default 14 if IDF_TARGET_ESP32
|
||||
default 12 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
default 6 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2
|
||||
default 4 if IDF_TARGET_ESP32H2
|
||||
help
|
||||
Set the GPIO number used by SPI SCLK.
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_MOSI_GPIO
|
||||
int "SPI MOSI GPIO number"
|
||||
range 0 33
|
||||
default 19
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||
default 13 if IDF_TARGET_ESP32
|
||||
default 11 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
default 7 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2
|
||||
default 5 if IDF_TARGET_ESP32H2
|
||||
help
|
||||
Set the GPIO number used by SPI MOSI.
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_MISO_GPIO
|
||||
int "SPI MISO GPIO number"
|
||||
range 0 33
|
||||
default 18
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
|
||||
default 12 if IDF_TARGET_ESP32
|
||||
default 13 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
default 2 if IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2
|
||||
default 0 if IDF_TARGET_ESP32H2
|
||||
help
|
||||
Set the GPIO number used by SPI MISO.
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_CS_GPIO
|
||||
int "SPI CS GPIO number"
|
||||
range 0 33
|
||||
default 21
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
help
|
||||
Set the GPIO number used by SPI CS.
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_CLOCK_MHZ
|
||||
int "SPI clock speed (MHz)"
|
||||
range 5 80
|
||||
default 36
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
default 12 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2 || IDF_TARGET_ESP32H2
|
||||
default 36 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
help
|
||||
Set the clock speed (MHz) of SPI interface.
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_INT_GPIO
|
||||
int "Interrupt GPIO number"
|
||||
default 4
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
config SNAPCLIENT_ETH_SPI_CS0_GPIO
|
||||
int "SPI CS0 GPIO number for SPI Ethernet module #1"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||
default 15 if IDF_TARGET_ESP32
|
||||
default 10 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C2
|
||||
default 1 if IDF_TARGET_ESP32H2
|
||||
help
|
||||
Set the GPIO number used by the SPI Ethernet module interrupt line.
|
||||
Set the GPIO number used by SPI CS0, i.e. Chip Select associated with the first SPI Eth module).
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_CS1_GPIO
|
||||
depends on SNAPCLIENT_SPI_ETHERNETS_NUM > 1
|
||||
int "SPI CS1 GPIO number for SPI Ethernet module #2"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_OUT_RANGE_MAX
|
||||
default 32 if IDF_TARGET_ESP32
|
||||
default 7 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32S3
|
||||
default 8 if IDF_TARGET_ESP32C3
|
||||
default 3 if IDF_TARGET_ESP32C2
|
||||
default 11 if IDF_TARGET_ESP32H2
|
||||
help
|
||||
Set the GPIO number used by SPI CS1, i.e. Chip Select associated with the second SPI Eth module.
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_INT0_GPIO
|
||||
int "Interrupt GPIO number SPI Ethernet module #1"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
|
||||
default 4 if IDF_TARGET_ESP32 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3
|
||||
default 4 if IDF_TARGET_ESP32C2
|
||||
default 9 if IDF_TARGET_ESP32H2
|
||||
help
|
||||
Set the GPIO number used by the first SPI Ethernet module interrupt line.
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_INT1_GPIO
|
||||
depends on SNAPCLIENT_SPI_ETHERNETS_NUM > 1
|
||||
int "Interrupt GPIO number SPI Ethernet module #2"
|
||||
range ENV_GPIO_RANGE_MIN ENV_GPIO_IN_RANGE_MAX
|
||||
default 33 if IDF_TARGET_ESP32
|
||||
default 5 if IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3 || IDF_TARGET_ESP32C2
|
||||
default 10 if IDF_TARGET_ESP32H2
|
||||
help
|
||||
Set the GPIO number used by the second SPI Ethernet module interrupt line.
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_PHY_RST0_GPIO
|
||||
int "PHY Reset GPIO number of SPI Ethernet Module #1"
|
||||
range -1 ENV_GPIO_OUT_RANGE_MAX
|
||||
default -1
|
||||
help
|
||||
Set the GPIO number used to reset PHY chip on the first SPI Ethernet module.
|
||||
Set to -1 to disable PHY chip hardware reset.
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_PHY_RST1_GPIO
|
||||
depends on SNAPCLIENT_SPI_ETHERNETS_NUM > 1
|
||||
int "PHY Reset GPIO number of SPI Ethernet Module #2"
|
||||
range -1 ENV_GPIO_OUT_RANGE_MAX
|
||||
default -1
|
||||
help
|
||||
Set the GPIO number used to reset PHY chip on the second SPI Ethernet module.
|
||||
Set to -1 to disable PHY chip hardware reset.
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_PHY_ADDR0
|
||||
int "PHY Address of SPI Ethernet Module #1"
|
||||
range 0 31
|
||||
default 1
|
||||
help
|
||||
Set the first SPI Ethernet module PHY address according your board schematic.
|
||||
|
||||
config SNAPCLIENT_ETH_SPI_PHY_ADDR1
|
||||
depends on SNAPCLIENT_SPI_ETHERNETS_NUM > 1
|
||||
int "PHY Address of SPI Ethernet Module #2"
|
||||
range 0 31
|
||||
default 1
|
||||
help
|
||||
Set the second SPI Ethernet module PHY address according your board schematic.
|
||||
endif # SNAPCLIENT_USE_SPI_ETHERNET
|
||||
|
||||
config SNAPCLIENT_ETH_PHY_RST_GPIO
|
||||
int "PHY Reset GPIO number"
|
||||
default 17
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
help
|
||||
Set the GPIO number used to reset PHY chip.
|
||||
Set to -1 to disable PHY chip hardware reset.
|
||||
|
||||
config SNAPCLIENT_ETH_PHY_ADDR
|
||||
int "PHY Address"
|
||||
range 0 31
|
||||
default 0
|
||||
depends on SNAPCLIENT_ENABLE_ETHERNET
|
||||
help
|
||||
Set PHY address according your board schematic.
|
||||
endmenu
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/* Ethernet Basic Example
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||
*/
|
||||
#include "eth_interface.h"
|
||||
|
||||
This example code is in the Public Domain (or CC0 licensed, at your option.)
|
||||
|
||||
Unless required by applicable law or agreed to in writing, this
|
||||
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
||||
CONDITIONS OF ANY KIND, either express or implied.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_check.h"
|
||||
#include "esp_eth.h"
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
@@ -19,16 +19,11 @@
|
||||
#include "freertos/event_groups.h"
|
||||
#include "freertos/task.h"
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_ETH_USE_SPI_ETHERNET
|
||||
#if CONFIG_SNAPCLIENT_USE_SPI_ETHERNET
|
||||
#include "driver/spi_master.h"
|
||||
#endif // CONFIG_ETH_USE_SPI_ETHERNET
|
||||
#endif
|
||||
|
||||
static const char *TAG = "ETH";
|
||||
|
||||
static esp_eth_handle_t s_eth_handle = NULL;
|
||||
static esp_eth_mac_t *s_mac = NULL;
|
||||
static esp_eth_phy_t *s_phy = NULL;
|
||||
static esp_eth_netif_glue_handle_t s_eth_glue = NULL;
|
||||
static const char *TAG = "snapclient_eth_init";
|
||||
|
||||
/* The event group allows multiple bits for each event, but we only care about
|
||||
* two events:
|
||||
@@ -39,11 +34,324 @@ static esp_eth_netif_glue_handle_t s_eth_glue = NULL;
|
||||
|
||||
static EventGroupHandle_t s_eth_event_group;
|
||||
|
||||
#if CONFIG_SNAPCLIENT_SPI_ETHERNETS_NUM
|
||||
#define SPI_ETHERNETS_NUM CONFIG_SNAPCLIENT_SPI_ETHERNETS_NUM
|
||||
#else
|
||||
#define SPI_ETHERNETS_NUM 0
|
||||
#endif
|
||||
|
||||
#if CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET
|
||||
#define INTERNAL_ETHERNETS_NUM 1
|
||||
#else
|
||||
#define INTERNAL_ETHERNETS_NUM 0
|
||||
#endif
|
||||
|
||||
#define INIT_SPI_ETH_MODULE_CONFIG(eth_module_config, num) \
|
||||
do { \
|
||||
eth_module_config[num].spi_cs_gpio = \
|
||||
CONFIG_SNAPCLIENT_ETH_SPI_CS##num##_GPIO; \
|
||||
eth_module_config[num].int_gpio = \
|
||||
CONFIG_SNAPCLIENT_ETH_SPI_INT##num##_GPIO; \
|
||||
eth_module_config[num].phy_reset_gpio = \
|
||||
CONFIG_SNAPCLIENT_ETH_SPI_PHY_RST##num##_GPIO; \
|
||||
eth_module_config[num].phy_addr = CONFIG_SNAPCLIENT_ETH_SPI_PHY_ADDR##num; \
|
||||
} while (0)
|
||||
|
||||
typedef struct {
|
||||
uint8_t spi_cs_gpio;
|
||||
uint8_t int_gpio;
|
||||
int8_t phy_reset_gpio;
|
||||
uint8_t phy_addr;
|
||||
uint8_t *mac_addr;
|
||||
} spi_eth_module_config_t;
|
||||
|
||||
#if CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET
|
||||
/**
|
||||
* @brief Internal ESP32 Ethernet initialization
|
||||
*
|
||||
* @param[out] mac_out optionally returns Ethernet MAC object
|
||||
* @param[out] phy_out optionally returns Ethernet PHY object
|
||||
* @return
|
||||
* - esp_eth_handle_t if init succeeded
|
||||
* - NULL if init failed
|
||||
*/
|
||||
static esp_eth_handle_t eth_init_internal(esp_eth_mac_t **mac_out,
|
||||
esp_eth_phy_t **phy_out) {
|
||||
esp_eth_handle_t ret = NULL;
|
||||
|
||||
// Init common MAC and PHY configs to default
|
||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||
|
||||
// Update PHY config based on board specific configuration
|
||||
phy_config.phy_addr = CONFIG_SNAPCLIENT_ETH_PHY_ADDR;
|
||||
phy_config.reset_gpio_num = CONFIG_SNAPCLIENT_ETH_PHY_RST_GPIO;
|
||||
|
||||
// Init vendor specific MAC config to default
|
||||
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
||||
// Update vendor specific MAC config based on board configuration
|
||||
esp32_emac_config.smi_mdc_gpio_num = CONFIG_SNAPCLIENT_ETH_MDC_GPIO;
|
||||
esp32_emac_config.smi_mdio_gpio_num = CONFIG_SNAPCLIENT_ETH_MDIO_GPIO;
|
||||
|
||||
// Set clock mode and GPIO
|
||||
#if CONFIG_ETH_RMII_CLK_INPUT
|
||||
esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_EXT_IN;
|
||||
#elif CONFIG_ETH_RMII_CLK_OUTPUT
|
||||
esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_EXT_OUT;
|
||||
#else
|
||||
esp32_emac_config.clock_config.rmii.clock_mode = EMAC_CLK_DEFAULT;
|
||||
#endif
|
||||
esp32_emac_config.clock_config.rmii.clock_gpio = CONFIG_ETH_RMII_CLK_IN_GPIO;
|
||||
|
||||
// Create new ESP32 Ethernet MAC instance
|
||||
esp_eth_mac_t *mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
||||
|
||||
// Create new PHY instance based on board configuration
|
||||
#if CONFIG_SNAPCLIENT_ETH_PHY_IP101
|
||||
esp_eth_phy_t *phy = esp_eth_phy_new_ip101(&phy_config);
|
||||
#elif CONFIG_SNAPCLIENT_ETH_PHY_RTL8201
|
||||
esp_eth_phy_t *phy = esp_eth_phy_new_rtl8201(&phy_config);
|
||||
#elif CONFIG_SNAPCLIENT_ETH_PHY_LAN87XX
|
||||
esp_eth_phy_t *phy = esp_eth_phy_new_lan87xx(&phy_config);
|
||||
#elif CONFIG_SNAPCLIENT_ETH_PHY_DP83848
|
||||
esp_eth_phy_t *phy = esp_eth_phy_new_dp83848(&phy_config);
|
||||
#elif CONFIG_SNAPCLIENT_ETH_PHY_KSZ80XX
|
||||
esp_eth_phy_t *phy = esp_eth_phy_new_ksz80xx(&phy_config);
|
||||
#endif
|
||||
|
||||
// Init Ethernet driver to default and install it
|
||||
esp_eth_handle_t eth_handle = NULL;
|
||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(mac, phy);
|
||||
ESP_GOTO_ON_FALSE(esp_eth_driver_install(&config, ð_handle) == ESP_OK,
|
||||
NULL, err, TAG, "Ethernet driver install failed");
|
||||
|
||||
if (mac_out != NULL) {
|
||||
*mac_out = mac;
|
||||
}
|
||||
if (phy_out != NULL) {
|
||||
*phy_out = phy;
|
||||
}
|
||||
return eth_handle;
|
||||
err:
|
||||
if (eth_handle != NULL) {
|
||||
esp_eth_driver_uninstall(eth_handle);
|
||||
}
|
||||
if (mac != NULL) {
|
||||
mac->del(mac);
|
||||
}
|
||||
if (phy != NULL) {
|
||||
phy->del(phy);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif // CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET
|
||||
|
||||
#if CONFIG_SNAPCLIENT_USE_SPI_ETHERNET
|
||||
/**
|
||||
* @brief SPI bus initialization (to be used by Ethernet SPI modules)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
static esp_err_t spi_bus_init(void) {
|
||||
esp_err_t ret = ESP_OK;
|
||||
|
||||
// Install GPIO ISR handler to be able to service SPI Eth modules interrupts
|
||||
ret = gpio_install_isr_service(0);
|
||||
if (ret != ESP_OK) {
|
||||
if (ret == ESP_ERR_INVALID_STATE) {
|
||||
ESP_LOGW(TAG, "GPIO ISR handler has been already installed");
|
||||
ret = ESP_OK; // ISR handler has been already installed so no issues
|
||||
} else {
|
||||
ESP_LOGE(TAG, "GPIO ISR handler install failed");
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
// Init SPI bus
|
||||
spi_bus_config_t buscfg = {
|
||||
.miso_io_num = CONFIG_SNAPCLIENT_ETH_SPI_MISO_GPIO,
|
||||
.mosi_io_num = CONFIG_SNAPCLIENT_ETH_SPI_MOSI_GPIO,
|
||||
.sclk_io_num = CONFIG_SNAPCLIENT_ETH_SPI_SCLK_GPIO,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
};
|
||||
ESP_GOTO_ON_ERROR(spi_bus_initialize(CONFIG_SNAPCLIENT_ETH_SPI_HOST, &buscfg,
|
||||
SPI_DMA_CH_AUTO),
|
||||
err, TAG, "SPI host #%d init failed",
|
||||
CONFIG_SNAPCLIENT_ETH_SPI_HOST);
|
||||
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ethernet SPI modules initialization
|
||||
*
|
||||
* @param[in] spi_eth_module_config specific SPI Ethernet module configuration
|
||||
* @param[out] mac_out optionally returns Ethernet MAC object
|
||||
* @param[out] phy_out optionally returns Ethernet PHY object
|
||||
* @return
|
||||
* - esp_eth_handle_t if init succeeded
|
||||
* - NULL if init failed
|
||||
*/
|
||||
static esp_eth_handle_t eth_init_spi(
|
||||
spi_eth_module_config_t *spi_eth_module_config, esp_eth_mac_t **mac_out,
|
||||
esp_eth_phy_t **phy_out) {
|
||||
esp_eth_handle_t ret = NULL;
|
||||
|
||||
// Init common MAC and PHY configs to default
|
||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||
|
||||
// Update PHY config based on board specific configuration
|
||||
phy_config.phy_addr = spi_eth_module_config->phy_addr;
|
||||
phy_config.reset_gpio_num = spi_eth_module_config->phy_reset_gpio;
|
||||
|
||||
// Configure SPI interface for specific SPI module
|
||||
spi_device_interface_config_t spi_devcfg = {
|
||||
.mode = 0,
|
||||
.clock_speed_hz = CONFIG_SNAPCLIENT_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
|
||||
.queue_size = 20,
|
||||
.spics_io_num = spi_eth_module_config->spi_cs_gpio};
|
||||
// Init vendor specific MAC config to default, and create new SPI Ethernet MAC
|
||||
// instance and new PHY instance based on board configuration
|
||||
#if CONFIG_SNAPCLIENT_USE_KSZ8851SNL
|
||||
eth_ksz8851snl_config_t ksz8851snl_config = ETH_KSZ8851SNL_DEFAULT_CONFIG(
|
||||
CONFIG_SNAPCLIENT_ETH_SPI_HOST, &spi_devcfg);
|
||||
ksz8851snl_config.int_gpio_num = spi_eth_module_config->int_gpio;
|
||||
esp_eth_mac_t *mac =
|
||||
esp_eth_mac_new_ksz8851snl(&ksz8851snl_config, &mac_config);
|
||||
esp_eth_phy_t *phy = esp_eth_phy_new_ksz8851snl(&phy_config);
|
||||
#elif CONFIG_SNAPCLIENT_USE_DM9051
|
||||
eth_dm9051_config_t dm9051_config =
|
||||
ETH_DM9051_DEFAULT_CONFIG(CONFIG_SNAPCLIENT_ETH_SPI_HOST, &spi_devcfg);
|
||||
dm9051_config.int_gpio_num = spi_eth_module_config->int_gpio;
|
||||
esp_eth_mac_t *mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
|
||||
esp_eth_phy_t *phy = esp_eth_phy_new_dm9051(&phy_config);
|
||||
#elif CONFIG_SNAPCLIENT_USE_W5500
|
||||
eth_w5500_config_t w5500_config =
|
||||
ETH_W5500_DEFAULT_CONFIG(CONFIG_SNAPCLIENT_ETH_SPI_HOST, &spi_devcfg);
|
||||
w5500_config.int_gpio_num = spi_eth_module_config->int_gpio;
|
||||
esp_eth_mac_t *mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
||||
esp_eth_phy_t *phy = esp_eth_phy_new_w5500(&phy_config);
|
||||
#endif // CONFIG_SNAPCLIENT_USE_W5500
|
||||
// Init Ethernet driver to default and install it
|
||||
esp_eth_handle_t eth_handle = NULL;
|
||||
esp_eth_config_t eth_config_spi = ETH_DEFAULT_CONFIG(mac, phy);
|
||||
ESP_GOTO_ON_FALSE(
|
||||
esp_eth_driver_install(ð_config_spi, ð_handle) == ESP_OK, NULL, err,
|
||||
TAG, "SPI Ethernet driver install failed");
|
||||
|
||||
// The SPI Ethernet module might not have a burned factory MAC address, we can
|
||||
// set it manually.
|
||||
if (spi_eth_module_config->mac_addr != NULL) {
|
||||
ESP_GOTO_ON_FALSE(esp_eth_ioctl(eth_handle, ETH_CMD_S_MAC_ADDR,
|
||||
spi_eth_module_config->mac_addr) == ESP_OK,
|
||||
NULL, err, TAG, "SPI Ethernet MAC address config failed");
|
||||
}
|
||||
|
||||
if (mac_out != NULL) {
|
||||
*mac_out = mac;
|
||||
}
|
||||
if (phy_out != NULL) {
|
||||
*phy_out = phy;
|
||||
}
|
||||
return eth_handle;
|
||||
err:
|
||||
if (eth_handle != NULL) {
|
||||
esp_eth_driver_uninstall(eth_handle);
|
||||
}
|
||||
if (mac != NULL) {
|
||||
mac->del(mac);
|
||||
}
|
||||
if (phy != NULL) {
|
||||
phy->del(phy);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif // CONFIG_SNAPCLIENT_USE_SPI_ETHERNET
|
||||
|
||||
/** Original init function in the example */
|
||||
esp_err_t original_eth_init(esp_eth_handle_t *eth_handles_out[],
|
||||
uint8_t *eth_cnt_out) {
|
||||
esp_err_t ret = ESP_OK;
|
||||
esp_eth_handle_t *eth_handles = NULL;
|
||||
uint8_t eth_cnt = 0;
|
||||
|
||||
#if CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET || \
|
||||
CONFIG_SNAPCLIENT_USE_SPI_ETHERNET
|
||||
ESP_GOTO_ON_FALSE(
|
||||
eth_handles_out != NULL && eth_cnt_out != NULL, ESP_ERR_INVALID_ARG, err,
|
||||
TAG,
|
||||
"invalid arguments: initialized handles array or number of interfaces");
|
||||
eth_handles = calloc(SPI_ETHERNETS_NUM + INTERNAL_ETHERNETS_NUM,
|
||||
sizeof(esp_eth_handle_t));
|
||||
ESP_GOTO_ON_FALSE(eth_handles != NULL, ESP_ERR_NO_MEM, err, TAG, "no memory");
|
||||
|
||||
#if CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET
|
||||
eth_handles[eth_cnt] = eth_init_internal(NULL, NULL);
|
||||
ESP_GOTO_ON_FALSE(eth_handles[eth_cnt], ESP_FAIL, err, TAG,
|
||||
"internal Ethernet init failed");
|
||||
eth_cnt++;
|
||||
#endif // CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET
|
||||
|
||||
#if CONFIG_SNAPCLIENT_USE_SPI_ETHERNET
|
||||
ESP_GOTO_ON_ERROR(spi_bus_init(), err, TAG, "SPI bus init failed");
|
||||
// Init specific SPI Ethernet module configuration from Kconfig (CS GPIO,
|
||||
// Interrupt GPIO, etc.)
|
||||
spi_eth_module_config_t
|
||||
spi_eth_module_config[CONFIG_SNAPCLIENT_SPI_ETHERNETS_NUM] = {0};
|
||||
INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 0);
|
||||
// The SPI Ethernet module(s) might not have a burned factory MAC address,
|
||||
// hence use manually configured address(es). In this example, Locally
|
||||
// Administered MAC address derived from ESP32x base MAC address is used. Note
|
||||
// that Locally Administered OUI range should be used only when testing on a
|
||||
// LAN under your control!
|
||||
uint8_t base_mac_addr[ETH_ADDR_LEN];
|
||||
ESP_GOTO_ON_ERROR(esp_efuse_mac_get_default(base_mac_addr), err, TAG,
|
||||
"get EFUSE MAC failed");
|
||||
uint8_t local_mac_1[ETH_ADDR_LEN];
|
||||
esp_derive_local_mac(local_mac_1, base_mac_addr);
|
||||
spi_eth_module_config[0].mac_addr = local_mac_1;
|
||||
#if CONFIG_SNAPCLIENT_SPI_ETHERNETS_NUM > 1
|
||||
INIT_SPI_ETH_MODULE_CONFIG(spi_eth_module_config, 1);
|
||||
uint8_t local_mac_2[ETH_ADDR_LEN];
|
||||
base_mac_addr[ETH_ADDR_LEN - 1] += 1;
|
||||
esp_derive_local_mac(local_mac_2, base_mac_addr);
|
||||
spi_eth_module_config[1].mac_addr = local_mac_2;
|
||||
#endif
|
||||
#if CONFIG_SNAPCLIENT_SPI_ETHERNETS_NUM > 2
|
||||
#error Maximum number of supported SPI Ethernet devices is currently limited to 2 by this example.
|
||||
#endif
|
||||
for (int i = 0; i < CONFIG_SNAPCLIENT_SPI_ETHERNETS_NUM; i++) {
|
||||
eth_handles[eth_cnt] = eth_init_spi(&spi_eth_module_config[i], NULL, NULL);
|
||||
ESP_GOTO_ON_FALSE(eth_handles[eth_cnt], ESP_FAIL, err, TAG,
|
||||
"SPI Ethernet init failed");
|
||||
eth_cnt++;
|
||||
}
|
||||
#endif // CONFIG_ETH_USE_SPI_ETHERNET
|
||||
#else
|
||||
ESP_LOGD(TAG, "no Ethernet device selected to init");
|
||||
#endif // CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET ||
|
||||
// CONFIG_SNAPCLIENT_USE_SPI_ETHERNET
|
||||
*eth_handles_out = eth_handles;
|
||||
*eth_cnt_out = eth_cnt;
|
||||
|
||||
return ret;
|
||||
#if CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET || \
|
||||
CONFIG_SNAPCLIENT_USE_SPI_ETHERNET
|
||||
err:
|
||||
free(eth_handles);
|
||||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
/** Event handler for Ethernet events */
|
||||
static void eth_event_handler(void *arg, esp_event_base_t event_base,
|
||||
int32_t event_id, void *event_data) {
|
||||
uint8_t mac_addr[6] = {0};
|
||||
/* we can get the Ethernet driver handle from event data */
|
||||
/* we can get the ethernet driver handle from event data */
|
||||
esp_eth_handle_t eth_handle = *(esp_eth_handle_t *)event_data;
|
||||
|
||||
switch (event_id) {
|
||||
@@ -53,7 +361,6 @@ static void eth_event_handler(void *arg, esp_event_base_t event_base,
|
||||
ESP_LOGI(TAG, "Ethernet HW Addr %02x:%02x:%02x:%02x:%02x:%02x",
|
||||
mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4],
|
||||
mac_addr[5]);
|
||||
|
||||
break;
|
||||
case ETHERNET_EVENT_DISCONNECTED:
|
||||
ESP_LOGI(TAG, "Ethernet Link Down");
|
||||
@@ -86,112 +393,64 @@ static void got_ip_event_handler(void *arg, esp_event_base_t event_base,
|
||||
xEventGroupSetBits(s_eth_event_group, ETH_CONNECTED_BIT);
|
||||
}
|
||||
|
||||
/** Init function that exposes to the main application */
|
||||
void eth_init(void) {
|
||||
// Initialize TCP/IP network interface (should be called only once in
|
||||
// application)
|
||||
// Initialize Ethernet driver
|
||||
uint8_t eth_port_cnt = 0;
|
||||
esp_eth_handle_t *eth_handles;
|
||||
ESP_ERROR_CHECK(original_eth_init(ð_handles, ð_port_cnt));
|
||||
|
||||
// Initialize TCP/IP network interface aka the esp-netif (should be called
|
||||
// only once in application)
|
||||
ESP_ERROR_CHECK(esp_netif_init());
|
||||
// Create default event loop that running in background
|
||||
ESP_ERROR_CHECK(esp_event_loop_create_default());
|
||||
|
||||
esp_netif_inherent_config_t esp_netif_config =
|
||||
ESP_NETIF_INHERENT_DEFAULT_ETH();
|
||||
// Warning: the interface desc is used in tests to capture actual connection
|
||||
// details (IP, gw, mask)
|
||||
esp_netif_config.if_desc = "eth";
|
||||
esp_netif_config.route_prio = 64;
|
||||
esp_netif_config_t netif_config = {.base = &esp_netif_config,
|
||||
.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH};
|
||||
esp_netif_t *netif = esp_netif_new(&netif_config);
|
||||
assert(netif);
|
||||
// Create instance(s) of esp-netif for Ethernet(s)
|
||||
if (eth_port_cnt == 1) {
|
||||
// Use ESP_NETIF_DEFAULT_ETH when just one Ethernet interface is used and
|
||||
// you don't need to modify default esp-netif configuration parameters.
|
||||
esp_netif_config_t cfg = ESP_NETIF_DEFAULT_ETH();
|
||||
esp_netif_t *eth_netif = esp_netif_new(&cfg);
|
||||
// Attach Ethernet driver to TCP/IP stack
|
||||
ESP_ERROR_CHECK(
|
||||
esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[0])));
|
||||
} else {
|
||||
// Use ESP_NETIF_INHERENT_DEFAULT_ETH when multiple Ethernet interfaces are
|
||||
// used and so you need to modify esp-netif configuration parameters for
|
||||
// each interface (name, priority, etc.).
|
||||
esp_netif_inherent_config_t esp_netif_config =
|
||||
ESP_NETIF_INHERENT_DEFAULT_ETH();
|
||||
esp_netif_config_t cfg_spi = {.base = &esp_netif_config,
|
||||
.stack = ESP_NETIF_NETSTACK_DEFAULT_ETH};
|
||||
char if_key_str[10];
|
||||
char if_desc_str[10];
|
||||
char num_str[3];
|
||||
for (int i = 0; i < eth_port_cnt; i++) {
|
||||
itoa(i, num_str, 10);
|
||||
strcat(strcpy(if_key_str, "ETH_"), num_str);
|
||||
strcat(strcpy(if_desc_str, "eth"), num_str);
|
||||
esp_netif_config.if_key = if_key_str;
|
||||
esp_netif_config.if_desc = if_desc_str;
|
||||
esp_netif_config.route_prio -= i * 5;
|
||||
esp_netif_t *eth_netif = esp_netif_new(&cfg_spi);
|
||||
|
||||
eth_mac_config_t mac_config = ETH_MAC_DEFAULT_CONFIG();
|
||||
mac_config.rx_task_stack_size = 2048;
|
||||
eth_phy_config_t phy_config = ETH_PHY_DEFAULT_CONFIG();
|
||||
phy_config.phy_addr = CONFIG_SNAPCLIENT_ETH_PHY_ADDR;
|
||||
phy_config.reset_gpio_num = CONFIG_SNAPCLIENT_ETH_PHY_RST_GPIO;
|
||||
#if CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET
|
||||
eth_esp32_emac_config_t esp32_emac_config = ETH_ESP32_EMAC_DEFAULT_CONFIG();
|
||||
esp32_emac_config.smi_mdc_gpio_num = CONFIG_SNAPCLIENT_ETH_MDC_GPIO;
|
||||
esp32_emac_config.smi_mdio_gpio_num = CONFIG_SNAPCLIENT_ETH_MDIO_GPIO;
|
||||
s_mac = esp_eth_mac_new_esp32(&esp32_emac_config, &mac_config);
|
||||
#if CONFIG_SNAPCLIENT_ETH_PHY_IP101
|
||||
s_phy = esp_eth_phy_new_ip101(&phy_config);
|
||||
#elif CONFIG_SNAPCLIENT_ETH_PHY_RTL8201
|
||||
s_phy = esp_eth_phy_new_rtl8201(&phy_config);
|
||||
#elif CONFIG_SNAPCLIENT_ETH_PHY_LAN8720
|
||||
s_phy = esp_eth_phy_new_lan87xx(&phy_config);
|
||||
#elif CONFIG_SNAPCLIENT_ETH_PHY_DP83848
|
||||
s_phy = esp_eth_phy_new_dp83848(&phy_config);
|
||||
#elif CONFIG_SNAPCLIENT_ETH_PHY_KSZ8041
|
||||
s_phy = esp_eth_phy_new_ksz80xx(&phy_config);
|
||||
#endif
|
||||
#elif CONFIG_SNAPCLIENT_USE_SPI_ETHERNET
|
||||
gpio_install_isr_service(0);
|
||||
spi_bus_config_t buscfg = {
|
||||
.miso_io_num = CONFIG_SNAPCLIENT_ETH_SPI_MISO_GPIO,
|
||||
.mosi_io_num = CONFIG_SNAPCLIENT_ETH_SPI_MOSI_GPIO,
|
||||
.sclk_io_num = CONFIG_SNAPCLIENT_ETH_SPI_SCLK_GPIO,
|
||||
.quadwp_io_num = -1,
|
||||
.quadhd_io_num = -1,
|
||||
};
|
||||
ESP_ERROR_CHECK(spi_bus_initialize(CONFIG_SNAPCLIENT_ETH_SPI_HOST, &buscfg,
|
||||
SPI_DMA_CH_AUTO));
|
||||
spi_device_interface_config_t spi_devcfg = {
|
||||
.mode = 0,
|
||||
.clock_speed_hz = CONFIG_SNAPCLIENT_ETH_SPI_CLOCK_MHZ * 1000 * 1000,
|
||||
.spics_io_num = CONFIG_SNAPCLIENT_ETH_SPI_CS_GPIO,
|
||||
.queue_size = 20};
|
||||
#if CONFIG_SNAPCLIENT_USE_DM9051
|
||||
/* dm9051 ethernet driver is based on spi driver */
|
||||
eth_dm9051_config_t dm9051_config =
|
||||
ETH_DM9051_DEFAULT_CONFIG(CONFIG_SNAPCLIENT_ETH_SPI_HOST, &spi_devcfg);
|
||||
dm9051_config.int_gpio_num = CONFIG_SNAPCLIENT_ETH_SPI_INT_GPIO;
|
||||
s_mac = esp_eth_mac_new_dm9051(&dm9051_config, &mac_config);
|
||||
s_phy = esp_eth_phy_new_dm9051(&phy_config);
|
||||
#elif CONFIG_SNAPCLIENT_USE_W5500
|
||||
/* w5500 ethernet driver is based on spi driver */
|
||||
eth_w5500_config_t w5500_config =
|
||||
ETH_W5500_DEFAULT_CONFIG(CONFIG_SNAPCLIENT_ETH_SPI_HOST, &spi_devcfg);
|
||||
w5500_config.int_gpio_num = CONFIG_SNAPCLIENT_ETH_SPI_INT_GPIO;
|
||||
s_mac = esp_eth_mac_new_w5500(&w5500_config, &mac_config);
|
||||
s_phy = esp_eth_phy_new_w5500(&phy_config);
|
||||
#endif
|
||||
#elif CONFIG_SNAPCLIENT_USE_OPENETH
|
||||
phy_config.autonego_timeout_ms = 100;
|
||||
s_mac = esp_eth_mac_new_openeth(&mac_config);
|
||||
s_phy = esp_eth_phy_new_dp83848(&phy_config);
|
||||
#endif
|
||||
|
||||
// Install Ethernet driver
|
||||
esp_eth_config_t config = ETH_DEFAULT_CONFIG(s_mac, s_phy);
|
||||
ESP_ERROR_CHECK(esp_eth_driver_install(&config, &s_eth_handle));
|
||||
#if !CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET
|
||||
/* The SPI Ethernet module might doesn't have a burned factory MAC address, we
|
||||
cat to set it manually. We set the ESP_MAC_ETH mac address as the default,
|
||||
if you want to use ESP_MAC_EFUSE_CUSTOM mac address, please enable the
|
||||
configuration: `ESP_MAC_USE_CUSTOM_MAC_AS_BASE_MAC`
|
||||
*/
|
||||
uint8_t eth_mac[6] = {0};
|
||||
ESP_ERROR_CHECK(esp_read_mac(eth_mac, ESP_MAC_ETH));
|
||||
ESP_ERROR_CHECK(esp_eth_ioctl(s_eth_handle, ETH_CMD_S_MAC_ADDR, eth_mac));
|
||||
#endif
|
||||
// combine driver with netif
|
||||
s_eth_glue = esp_eth_new_netif_glue(s_eth_handle);
|
||||
esp_netif_attach(netif, s_eth_glue);
|
||||
// Attach Ethernet driver to TCP/IP stack
|
||||
ESP_ERROR_CHECK(
|
||||
esp_netif_attach(eth_netif, esp_eth_new_netif_glue(eth_handles[i])));
|
||||
}
|
||||
}
|
||||
|
||||
// Register user defined event handers
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID,
|
||||
ð_event_handler, NULL));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_ETH_GOT_IP,
|
||||
&got_ip_event_handler, NULL));
|
||||
#ifdef CONFIG_SNAPCLIENT_CONNECT_IPV6
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(
|
||||
ETH_EVENT, ETHERNET_EVENT_CONNECTED, &on_eth_event, netif));
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_GOT_IP6,
|
||||
ð_on_got_ipv6, NULL));
|
||||
#endif
|
||||
|
||||
esp_eth_start(s_eth_handle);
|
||||
// Start Ethernet driver state machine
|
||||
for (int i = 0; i < eth_port_cnt; i++) {
|
||||
ESP_ERROR_CHECK(esp_eth_start(eth_handles[i]));
|
||||
}
|
||||
|
||||
/* Waiting until either the connection is established (ETH_CONNECTED_BIT) or
|
||||
* connection failed for the maximum number of re-tries (ETH_FAIL_BIT). The
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
#ifndef _ETH_INTERFACE_H_
|
||||
#define _ETH_INTERFACE_H_
|
||||
#pragma once
|
||||
|
||||
#include "esp_eth_driver.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void eth_init(void);
|
||||
|
||||
#endif /* _ETH_INTERFACE_H_ */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
11
components/improv_wifi/CMakeLists.txt
Normal file
11
components/improv_wifi/CMakeLists.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
# Build as an ESP-IDF component
|
||||
idf_component_register(
|
||||
SRCS "improvWifi.cpp" "improv_wrapper.cpp" "wifi_provisioning.c"
|
||||
PRIV_INCLUDE_DIRS "Improv-WiFi-Library/src" "priv_include"
|
||||
INCLUDE_DIRS "include"
|
||||
PRIV_REQUIRES driver esp_wifi wifi_interface
|
||||
#SRCS "Improv-WiFi-Library/src/ImprovWiFiLibrary.cpp" "wifi_provisioning.c"
|
||||
#INCLUDE_DIRS "Improv-WiFi-Library/src" "include"
|
||||
)
|
||||
1
components/improv_wifi/Improv-WiFi-Library
Submodule
1
components/improv_wifi/Improv-WiFi-Library
Submodule
Submodule components/improv_wifi/Improv-WiFi-Library added at f02cb67263
414
components/improv_wifi/improvWifi.cpp
Normal file
414
components/improv_wifi/improvWifi.cpp
Normal file
@@ -0,0 +1,414 @@
|
||||
/*
|
||||
* improvWifi.cpp
|
||||
*
|
||||
* Created on: Apr 29, 2024
|
||||
* Author: karl
|
||||
*/
|
||||
#include "improvWifi.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
void ImprovWiFi::handleSerial(const uint8_t *data, size_t length) {
|
||||
while (data && (length > 0)) {
|
||||
uint8_t b = *data;
|
||||
|
||||
if (parseImprovSerial(_position, b, _buffer)) {
|
||||
_buffer[_position++] = b;
|
||||
} else {
|
||||
_position = 0;
|
||||
}
|
||||
|
||||
length--;
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
void ImprovWiFi::SerialWriteCallback(const unsigned char *txData, int length) {
|
||||
if (serWriteCallback) {
|
||||
serWriteCallback(txData, length);
|
||||
}
|
||||
}
|
||||
|
||||
void ImprovWiFi::onErrorCallback(ImprovTypes::Error err) {
|
||||
if (onImproErrorCallback) {
|
||||
onImproErrorCallback(err);
|
||||
}
|
||||
}
|
||||
|
||||
bool ImprovWiFi::onCommandCallback(ImprovTypes::ImprovCommand cmd) {
|
||||
switch (cmd.command) {
|
||||
case ImprovTypes::Command::GET_CURRENT_STATE: {
|
||||
if (isConnected()) {
|
||||
setState(ImprovTypes::State::STATE_PROVISIONED);
|
||||
sendDeviceUrl(cmd.command);
|
||||
} else {
|
||||
setState(ImprovTypes::State::STATE_AUTHORIZED);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ImprovTypes::Command::WIFI_SETTINGS: {
|
||||
if (cmd.ssid.empty()) {
|
||||
setError(ImprovTypes::Error::ERROR_INVALID_RPC);
|
||||
break;
|
||||
}
|
||||
|
||||
setState(ImprovTypes::STATE_PROVISIONING);
|
||||
|
||||
bool success = false;
|
||||
|
||||
if (customConnectWiFiCallback) {
|
||||
success =
|
||||
customConnectWiFiCallback(cmd.ssid.c_str(), cmd.password.c_str());
|
||||
}
|
||||
|
||||
if (success) {
|
||||
setError(ImprovTypes::Error::ERROR_NONE);
|
||||
setState(ImprovTypes::STATE_PROVISIONED);
|
||||
sendDeviceUrl(cmd.command);
|
||||
if (onImprovConnectedCallback) {
|
||||
onImprovConnectedCallback(cmd.ssid.c_str(), cmd.password.c_str());
|
||||
}
|
||||
} else {
|
||||
setState(ImprovTypes::STATE_STOPPED);
|
||||
setError(ImprovTypes::ERROR_UNABLE_TO_CONNECT);
|
||||
onErrorCallback(ImprovTypes::ERROR_UNABLE_TO_CONNECT);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case ImprovTypes::Command::GET_DEVICE_INFO: {
|
||||
std::vector<std::string> infos = {
|
||||
// Firmware name
|
||||
improvWiFiParams.firmwareName,
|
||||
// Firmware version
|
||||
improvWiFiParams.firmwareVersion,
|
||||
// Hardware chip/variant
|
||||
CHIP_FAMILY_DESC[improvWiFiParams.chipFamily],
|
||||
// Device name
|
||||
improvWiFiParams.deviceName};
|
||||
std::vector<uint8_t> data =
|
||||
build_rpc_response(ImprovTypes::GET_DEVICE_INFO, infos, false);
|
||||
sendResponse(data);
|
||||
break;
|
||||
}
|
||||
|
||||
case ImprovTypes::Command::GET_WIFI_NETWORKS: {
|
||||
getAvailableWifiNetworks();
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
setError(ImprovTypes::ERROR_UNKNOWN_RPC);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
void ImprovWiFi::setDeviceInfo(ImprovTypes::ChipFamily chipFamily,
|
||||
const char *firmwareName,
|
||||
const char *firmwareVersion,
|
||||
const char *deviceName) {
|
||||
improvWiFiParams.chipFamily = chipFamily;
|
||||
improvWiFiParams.firmwareName = firmwareName;
|
||||
improvWiFiParams.firmwareVersion = firmwareVersion;
|
||||
improvWiFiParams.deviceName = deviceName;
|
||||
}
|
||||
void ImprovWiFi::setDeviceInfo(ImprovTypes::ChipFamily chipFamily,
|
||||
const char *firmwareName,
|
||||
const char *firmwareVersion,
|
||||
const char *deviceName, const char *deviceUrl) {
|
||||
setDeviceInfo(chipFamily, firmwareName, firmwareVersion, deviceName);
|
||||
improvWiFiParams.deviceUrl = deviceUrl;
|
||||
}
|
||||
|
||||
bool ImprovWiFi::isConnected() {
|
||||
if (customIsConnectedCallback) {
|
||||
customIsConnectedCallback();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ImprovWiFi::sendDeviceUrl(ImprovTypes::Command cmd) {
|
||||
// URL where user can finish onboarding or use device
|
||||
// Recommended to use website hosted by device
|
||||
|
||||
uint8_t address[4] = {0, 0, 0, 0};
|
||||
char buffer[16];
|
||||
|
||||
if (customGetLocalIpCallback) {
|
||||
customGetLocalIpCallback(address);
|
||||
}
|
||||
sprintf(buffer, "%d.%d.%d.%d", address[0], address[1], address[2],
|
||||
address[3]);
|
||||
std::string ipStr = std::string{buffer};
|
||||
|
||||
if (improvWiFiParams.deviceUrl.empty()) {
|
||||
improvWiFiParams.deviceUrl = "http://" + ipStr;
|
||||
} else {
|
||||
replaceAll(improvWiFiParams.deviceUrl, "{LOCAL_IPV4}", ipStr);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> data =
|
||||
build_rpc_response(cmd, {improvWiFiParams.deviceUrl}, false);
|
||||
sendResponse(data);
|
||||
}
|
||||
|
||||
void ImprovWiFi::serialWrite(SerialWrite *serWriteCb) {
|
||||
serWriteCallback = serWriteCb;
|
||||
}
|
||||
|
||||
void ImprovWiFi::onImprovError(OnImprovError *errorCallback) {
|
||||
onImproErrorCallback = errorCallback;
|
||||
}
|
||||
|
||||
void ImprovWiFi::onImprovConnected(OnImprovConnected *connectedCallback) {
|
||||
onImprovConnectedCallback = connectedCallback;
|
||||
}
|
||||
|
||||
void ImprovWiFi::setCustomConnectWiFi(CustomConnectWiFi *connectWiFiCallBack) {
|
||||
customConnectWiFiCallback = connectWiFiCallBack;
|
||||
}
|
||||
|
||||
void ImprovWiFi::setCustomScanWiFi(CustomScanWiFi *scanWiFiCallBack) {
|
||||
customScanWiFiCallback = scanWiFiCallBack;
|
||||
}
|
||||
|
||||
void ImprovWiFi::setCustomisConnected(CustomIsConnected *isConnectedCallBack) {
|
||||
customIsConnectedCallback = isConnectedCallBack;
|
||||
}
|
||||
|
||||
void ImprovWiFi::setCustomGetLocalIpCallback(
|
||||
CustomGetLocalIpCallback *getLocalIpCallback) {
|
||||
customGetLocalIpCallback = getLocalIpCallback;
|
||||
}
|
||||
|
||||
// for string delimiter
|
||||
std::vector<std::string> ImprovWiFi::split(std::string s,
|
||||
std::string delimiter) {
|
||||
size_t pos_start = 0, pos_end, delim_len = delimiter.length();
|
||||
std::string token;
|
||||
std::vector<std::string> res;
|
||||
|
||||
while ((pos_end = s.find(delimiter, pos_start)) != std::string::npos) {
|
||||
token = s.substr(pos_start, pos_end - pos_start);
|
||||
pos_start = pos_end + delim_len;
|
||||
res.push_back(token);
|
||||
}
|
||||
|
||||
res.push_back(s.substr(pos_start));
|
||||
return res;
|
||||
}
|
||||
|
||||
void ImprovWiFi::getAvailableWifiNetworks() {
|
||||
unsigned char apBuffer[256] = {
|
||||
0,
|
||||
};
|
||||
uint16_t networkNum = 0;
|
||||
int bufLen = sizeof(apBuffer);
|
||||
|
||||
// printf("scanning\n");
|
||||
|
||||
if (customScanWiFiCallback) {
|
||||
customScanWiFiCallback(apBuffer, bufLen, &networkNum);
|
||||
}
|
||||
|
||||
size_t pos = 0;
|
||||
std::string token;
|
||||
std::string delimiter = "\n";
|
||||
std::string apString{std::begin(apBuffer), std::end(apBuffer)};
|
||||
|
||||
for (int id = 0; id < networkNum; ++id) {
|
||||
if ((pos = apString.find(delimiter)) != std::string::npos) {
|
||||
token = apString.substr(0, pos);
|
||||
|
||||
std::vector<std::string> splitStr = split(token.c_str(), ",");
|
||||
|
||||
std::vector<std::string> wifinetworks = {splitStr};
|
||||
|
||||
std::vector<uint8_t> data = build_rpc_response(
|
||||
ImprovTypes::GET_WIFI_NETWORKS, wifinetworks, false);
|
||||
sendResponse(data);
|
||||
|
||||
apString.erase(0, pos + delimiter.length());
|
||||
}
|
||||
}
|
||||
// final response
|
||||
std::vector<uint8_t> data = build_rpc_response(
|
||||
ImprovTypes::GET_WIFI_NETWORKS, std::vector<std::string>{}, false);
|
||||
sendResponse(data);
|
||||
}
|
||||
|
||||
inline void ImprovWiFi::replaceAll(std::string &str, const std::string &from,
|
||||
const std::string &to) {
|
||||
size_t start_pos = 0;
|
||||
while ((start_pos = str.find(from, start_pos)) != std::string::npos) {
|
||||
str.replace(start_pos, from.length(), to);
|
||||
start_pos += to.length();
|
||||
}
|
||||
}
|
||||
|
||||
bool ImprovWiFi::parseImprovSerial(size_t position, uint8_t byte,
|
||||
const uint8_t *buffer) {
|
||||
if (position == 0) return byte == 'I';
|
||||
if (position == 1) return byte == 'M';
|
||||
if (position == 2) return byte == 'P';
|
||||
if (position == 3) return byte == 'R';
|
||||
if (position == 4) return byte == 'O';
|
||||
if (position == 5) return byte == 'V';
|
||||
|
||||
if (position == 6) {
|
||||
return byte == ImprovTypes::IMPROV_SERIAL_VERSION;
|
||||
}
|
||||
|
||||
if (position <= 8) return true;
|
||||
|
||||
uint8_t type = buffer[7];
|
||||
uint8_t data_len = buffer[8];
|
||||
|
||||
if (position <= 8 + data_len) return true;
|
||||
|
||||
if (position == 8 + data_len + 1) {
|
||||
uint8_t checksum = 0x00;
|
||||
for (size_t i = 0; i < position; i++) checksum += buffer[i];
|
||||
|
||||
if (checksum != byte) {
|
||||
_position = 0;
|
||||
onErrorCallback(ImprovTypes::Error::ERROR_INVALID_RPC);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (type == ImprovTypes::ImprovSerialType::TYPE_RPC) {
|
||||
_position = 0;
|
||||
auto command = parseImprovData(&buffer[9], data_len, false);
|
||||
return onCommandCallback(command);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
ImprovTypes::ImprovCommand ImprovWiFi::parseImprovData(
|
||||
const std::vector<uint8_t> &data, bool check_checksum) {
|
||||
return parseImprovData(data.data(), data.size(), check_checksum);
|
||||
}
|
||||
|
||||
ImprovTypes::ImprovCommand ImprovWiFi::parseImprovData(const uint8_t *data,
|
||||
size_t length,
|
||||
bool check_checksum) {
|
||||
ImprovTypes::ImprovCommand improv_command;
|
||||
ImprovTypes::Command command = (ImprovTypes::Command)data[0];
|
||||
uint8_t data_length = data[1];
|
||||
|
||||
if (data_length != length - 2 - check_checksum) {
|
||||
improv_command.command = ImprovTypes::Command::UNKNOWN;
|
||||
return improv_command;
|
||||
}
|
||||
|
||||
if (check_checksum) {
|
||||
uint8_t checksum = data[length - 1];
|
||||
|
||||
uint32_t calculated_checksum = 0;
|
||||
for (uint8_t i = 0; i < length - 1; i++) {
|
||||
calculated_checksum += data[i];
|
||||
}
|
||||
|
||||
if ((uint8_t)calculated_checksum != checksum) {
|
||||
improv_command.command = ImprovTypes::Command::BAD_CHECKSUM;
|
||||
return improv_command;
|
||||
}
|
||||
}
|
||||
|
||||
if (command == ImprovTypes::Command::WIFI_SETTINGS) {
|
||||
uint8_t ssid_length = data[2];
|
||||
uint8_t ssid_start = 3;
|
||||
size_t ssid_end = ssid_start + ssid_length;
|
||||
|
||||
uint8_t pass_length = data[ssid_end];
|
||||
size_t pass_start = ssid_end + 1;
|
||||
size_t pass_end = pass_start + pass_length;
|
||||
|
||||
std::string ssid(data + ssid_start, data + ssid_end);
|
||||
std::string password(data + pass_start, data + pass_end);
|
||||
|
||||
return {.command = command, .ssid = ssid, .password = password};
|
||||
}
|
||||
|
||||
improv_command.command = command;
|
||||
|
||||
return improv_command;
|
||||
}
|
||||
|
||||
void ImprovWiFi::setState(ImprovTypes::State state) {
|
||||
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
||||
data.resize(11);
|
||||
data[6] = ImprovTypes::IMPROV_SERIAL_VERSION;
|
||||
data[7] = ImprovTypes::TYPE_CURRENT_STATE;
|
||||
data[8] = 1;
|
||||
data[9] = state;
|
||||
|
||||
uint8_t checksum = 0x00;
|
||||
for (uint8_t d : data) checksum += d;
|
||||
data[10] = checksum;
|
||||
|
||||
SerialWriteCallback(data.data(), data.size());
|
||||
}
|
||||
|
||||
void ImprovWiFi::setError(ImprovTypes::Error error) {
|
||||
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
||||
data.resize(11);
|
||||
data[6] = ImprovTypes::IMPROV_SERIAL_VERSION;
|
||||
data[7] = ImprovTypes::TYPE_ERROR_STATE;
|
||||
data[8] = 1;
|
||||
data[9] = error;
|
||||
|
||||
uint8_t checksum = 0x00;
|
||||
for (uint8_t d : data) checksum += d;
|
||||
data[10] = checksum;
|
||||
|
||||
SerialWriteCallback(data.data(), data.size());
|
||||
}
|
||||
|
||||
void ImprovWiFi::sendResponse(std::vector<uint8_t> &response) {
|
||||
std::vector<uint8_t> data = {'I', 'M', 'P', 'R', 'O', 'V'};
|
||||
data.resize(9);
|
||||
data[6] = ImprovTypes::IMPROV_SERIAL_VERSION;
|
||||
data[7] = ImprovTypes::TYPE_RPC_RESPONSE;
|
||||
data[8] = response.size();
|
||||
data.insert(data.end(), response.begin(), response.end());
|
||||
|
||||
uint8_t checksum = 0x00;
|
||||
for (uint8_t d : data) checksum += d;
|
||||
data.push_back(checksum);
|
||||
|
||||
SerialWriteCallback(data.data(), data.size());
|
||||
}
|
||||
|
||||
std::vector<uint8_t> ImprovWiFi::build_rpc_response(
|
||||
ImprovTypes::Command command, const std::vector<std::string> &datum,
|
||||
bool add_checksum) {
|
||||
std::vector<uint8_t> out;
|
||||
uint32_t length = 0;
|
||||
out.push_back(command);
|
||||
for (const auto &str : datum) {
|
||||
uint8_t len = str.length();
|
||||
length += len + 1;
|
||||
out.push_back(len);
|
||||
out.insert(out.end(), str.begin(), str.end());
|
||||
}
|
||||
out.insert(out.begin() + 1, length);
|
||||
|
||||
if (add_checksum) {
|
||||
uint32_t calculated_checksum = 0;
|
||||
|
||||
for (uint8_t byte : out) {
|
||||
calculated_checksum += byte;
|
||||
}
|
||||
out.push_back(calculated_checksum);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
100
components/improv_wifi/improv_wrapper.cpp
Normal file
100
components/improv_wifi/improv_wrapper.cpp
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* improv_wrapper.cpp
|
||||
*
|
||||
* Created on: Apr 28, 2024
|
||||
* Author: karl
|
||||
*/
|
||||
#include "improv_wrapper.h"
|
||||
|
||||
ImprovWiFi *c = NULL;
|
||||
|
||||
extern "C" void improv_wifi_create(void) {
|
||||
if (c != NULL) {
|
||||
delete c;
|
||||
}
|
||||
|
||||
c = new ImprovWiFi();
|
||||
}
|
||||
|
||||
extern "C" void improv_wifi_destroy(void) {
|
||||
if (c != NULL) {
|
||||
delete c;
|
||||
c = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int improv_wifi_handle_serial(const uint8_t *data, size_t length) {
|
||||
if (c != NULL) {
|
||||
c->handleSerial(data, length);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
extern "C" void improv_wifi_set_device_info(uint8_t chipFamily,
|
||||
const char *firmwareName,
|
||||
const char *firmwareVersion,
|
||||
const char *deviceName,
|
||||
const char *deviceUrl) {
|
||||
if (c != NULL) {
|
||||
c->setDeviceInfo((ImprovTypes::ChipFamily)chipFamily, firmwareName,
|
||||
firmwareVersion, deviceName, deviceUrl);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void improv_wifi_serialWrite(void *serWriteCb) {
|
||||
ImprovWiFi::SerialWrite *cb = (ImprovWiFi::SerialWrite *)serWriteCb;
|
||||
if (c != NULL) {
|
||||
c->serialWrite(cb);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void improv_wifi_onImprovError(void *onImprovErrorCb) {
|
||||
ImprovWiFi::OnImprovError *cb = (ImprovWiFi::OnImprovError *)onImprovErrorCb;
|
||||
if (c != NULL) {
|
||||
c->onImprovError(cb);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void improv_wifi_onImprovConnected(void *onImprovConnectedCb) {
|
||||
ImprovWiFi::OnImprovConnected *cb =
|
||||
(ImprovWiFi::OnImprovConnected *)onImprovConnectedCb;
|
||||
if (c != NULL) {
|
||||
c->onImprovConnected(cb);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void improv_wifi_setCustomConnectWiFi(void *setCustomConnectWiFiCb) {
|
||||
ImprovWiFi::CustomConnectWiFi *cb =
|
||||
(ImprovWiFi::CustomConnectWiFi *)setCustomConnectWiFiCb;
|
||||
if (c != NULL) {
|
||||
c->setCustomConnectWiFi(cb);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void improv_wifi_setCustomScanWiFi(void *setCustomScanWiFiCb) {
|
||||
ImprovWiFi::CustomScanWiFi *cb =
|
||||
(ImprovWiFi::CustomScanWiFi *)setCustomScanWiFiCb;
|
||||
if (c != NULL) {
|
||||
c->setCustomScanWiFi(cb);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void improv_wifi_setCustomIsConnected(void *setCustomIsConnected) {
|
||||
ImprovWiFi::CustomIsConnected *cb =
|
||||
(ImprovWiFi::CustomIsConnected *)setCustomIsConnected;
|
||||
if (c != NULL) {
|
||||
c->setCustomisConnected(cb);
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" void improv_wifi_setCustomGetLocalIpCallback(
|
||||
void *getLocalIpCallback) {
|
||||
ImprovWiFi::CustomGetLocalIpCallback *cb =
|
||||
(ImprovWiFi::CustomGetLocalIpCallback *)getLocalIpCallback;
|
||||
if (c != NULL) {
|
||||
c->setCustomGetLocalIpCallback(cb);
|
||||
}
|
||||
}
|
||||
22
components/improv_wifi/include/wifi_provisioning.h
Normal file
22
components/improv_wifi/include/wifi_provisioning.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* wifi_provisioning.h
|
||||
*
|
||||
* Created on: Apr 28, 2024
|
||||
* Author: karl
|
||||
*/
|
||||
|
||||
#ifndef COMPONENTS_WIFI_PROVISIONING_H_
|
||||
#define COMPONENTS_WIFI_PROVISIONING_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void improv_init(void);
|
||||
void improv_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* COMPONENTS_WIFI_PROVISIONING_H_ */
|
||||
215
components/improv_wifi/priv_include/improvWifi.h
Normal file
215
components/improv_wifi/priv_include/improvWifi.h
Normal file
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* improvWifi.h
|
||||
*
|
||||
* Created on: Apr 29, 2024
|
||||
* Author: karl
|
||||
*/
|
||||
|
||||
#ifndef COMPONENTS_IMPROV_WIFI_INCLUDE_IMPROVWIFI_H_
|
||||
#define COMPONENTS_IMPROV_WIFI_INCLUDE_IMPROVWIFI_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ImprovTypes.h"
|
||||
|
||||
/**
|
||||
* Improv WiFi class
|
||||
*
|
||||
* ### Description
|
||||
*
|
||||
* Handles the Improv WiFi Serial protocol (https://www.improv-wifi.com/serial/)
|
||||
*
|
||||
* ### Example
|
||||
*
|
||||
* Simple example of using ImprovWiFi lib. A complete one can be seen in
|
||||
* `examples/` folder.
|
||||
*
|
||||
* ```cpp
|
||||
* #include <ImprovWiFiLibrary.h>
|
||||
*
|
||||
* ImprovWiFi improvSerial(&Serial);
|
||||
*
|
||||
* void setup() {
|
||||
* improvSerial.setDeviceInfo(ImprovTypes::ChipFamily::CF_ESP32,
|
||||
* "My-Device-9a4c2b", "2.1.5", "My Device");
|
||||
* }
|
||||
*
|
||||
* void loop() {
|
||||
* improvSerial.handleSerial();
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
class ImprovWiFi {
|
||||
private:
|
||||
const char *const CHIP_FAMILY_DESC[5] = {"ESP32", "ESP32-C3", "ESP32-S2",
|
||||
"ESP32-S3", "ESP8266"};
|
||||
ImprovTypes::ImprovWiFiParamsStruct improvWiFiParams;
|
||||
|
||||
uint8_t _buffer[128];
|
||||
uint8_t _position = 0;
|
||||
|
||||
// void *serial;
|
||||
|
||||
void sendDeviceUrl(ImprovTypes::Command cmd);
|
||||
void SerialWriteCallback(const unsigned char *txData, int length);
|
||||
bool onCommandCallback(ImprovTypes::ImprovCommand cmd);
|
||||
void onErrorCallback(ImprovTypes::Error err);
|
||||
void setState(ImprovTypes::State state);
|
||||
void sendResponse(std::vector<uint8_t> &response);
|
||||
void setError(ImprovTypes::Error error);
|
||||
void getAvailableWifiNetworks();
|
||||
inline void replaceAll(std::string &str, const std::string &from,
|
||||
const std::string &to);
|
||||
|
||||
// improv SDK
|
||||
bool parseImprovSerial(size_t position, uint8_t byte, const uint8_t *buffer);
|
||||
ImprovTypes::ImprovCommand parseImprovData(const std::vector<uint8_t> &data,
|
||||
bool check_checksum = true);
|
||||
ImprovTypes::ImprovCommand parseImprovData(const uint8_t *data, size_t length,
|
||||
bool check_checksum = true);
|
||||
std::vector<uint8_t> build_rpc_response(ImprovTypes::Command command,
|
||||
const std::vector<std::string> &datum,
|
||||
bool add_checksum);
|
||||
|
||||
public:
|
||||
/**
|
||||
* ## Constructors
|
||||
**/
|
||||
|
||||
/**
|
||||
* Create an instance of ImprovWiFi
|
||||
*
|
||||
* # Parameters
|
||||
*
|
||||
* - `serial` - Pointer to stream object used to handle requests, for the most
|
||||
* cases use `Serial`
|
||||
*/
|
||||
ImprovWiFi(void) {}
|
||||
|
||||
/**
|
||||
* ## Type definition
|
||||
*/
|
||||
|
||||
/**
|
||||
* serial write function passed through user
|
||||
*/
|
||||
typedef void(SerialWrite)(const unsigned char *txData, int length);
|
||||
|
||||
/**
|
||||
* Callback function called when any error occurs during the protocol handling
|
||||
* or wifi connection.
|
||||
*/
|
||||
typedef void(OnImprovError)(ImprovTypes::Error);
|
||||
|
||||
/**
|
||||
* Callback function called when the attempt of wifi connection is successful.
|
||||
* It informs the SSID and Password used to that, it's a perfect time to save
|
||||
* them for further use.
|
||||
*/
|
||||
typedef void(OnImprovConnected)(const char *ssid, const char *password);
|
||||
|
||||
/**
|
||||
* Callback function to customize the wifi connection if you needed. Optional.
|
||||
*/
|
||||
typedef bool(CustomConnectWiFi)(const char *ssid, const char *password);
|
||||
|
||||
typedef void(CustomScanWiFi)(unsigned char *scanResponse, int bufLen,
|
||||
uint16_t *count);
|
||||
|
||||
typedef bool(CustomIsConnected)(void);
|
||||
|
||||
typedef void(CustomGetLocalIpCallback)(uint8_t *addrIp4);
|
||||
|
||||
/**
|
||||
* ## Methods
|
||||
**/
|
||||
|
||||
/**
|
||||
* Check if a communication via serial is happening. Put this call on your
|
||||
* loop().
|
||||
*
|
||||
*/
|
||||
void handleSerial(const uint8_t *data, size_t length);
|
||||
|
||||
/**
|
||||
* Set details of your device.
|
||||
*
|
||||
* # Parameters
|
||||
*
|
||||
* - `chipFamily` - Chip variant, supported are CF_ESP32, CF_ESP32_C3,
|
||||
* CF_ESP32_S2, CF_ESP32_S3, CF_ESP8266. Consult ESP Home
|
||||
* [docs](https://esphome.io/components/esp32.html) for more information.
|
||||
* - `firmwareName` - Firmware name
|
||||
* - `firmwareVersion` - Firmware version
|
||||
* - `deviceName` - Your device name
|
||||
* - `deviceUrl`- The local URL to access your device. A placeholder called
|
||||
* {LOCAL_IPV4} is available to form elaboreted URLs. E.g.
|
||||
* `http://{LOCAL_IPV4}?name=Guest`. There is overloaded method without
|
||||
* `deviceUrl`, in this case the URL will be the local IP.
|
||||
*
|
||||
*/
|
||||
void setDeviceInfo(ImprovTypes::ChipFamily chipFamily,
|
||||
const char *firmwareName, const char *firmwareVersion,
|
||||
const char *deviceName, const char *deviceUrl);
|
||||
void setDeviceInfo(ImprovTypes::ChipFamily chipFamily,
|
||||
const char *firmwareName, const char *firmwareVersion,
|
||||
const char *deviceName);
|
||||
|
||||
/**
|
||||
* Method to set serial write callback
|
||||
*/
|
||||
void serialWrite(SerialWrite *serWriteCb);
|
||||
|
||||
/**
|
||||
* Method to set the typedef OnImprovError callback.
|
||||
*/
|
||||
void onImprovError(OnImprovError *errorCallback);
|
||||
|
||||
/**
|
||||
* Method to set the typedef OnImprovConnected callback.
|
||||
*/
|
||||
void onImprovConnected(OnImprovConnected *connectedCallback);
|
||||
|
||||
/**
|
||||
* Method to set the typedef CustomConnectWiFi callback.
|
||||
*/
|
||||
void setCustomConnectWiFi(CustomConnectWiFi *connectWiFiCallBack);
|
||||
|
||||
void setCustomScanWiFi(CustomScanWiFi *scanWiFiCallBack);
|
||||
|
||||
void setCustomisConnected(CustomIsConnected *isConnectedCallBack);
|
||||
|
||||
void setCustomGetLocalIpCallback(
|
||||
CustomGetLocalIpCallback *getLocalIpCallback);
|
||||
//
|
||||
// /**
|
||||
// * Default method to connect in a WiFi network.
|
||||
// * It waits `DELAY_MS_WAIT_WIFI_CONNECTION` milliseconds (default 500)
|
||||
// during
|
||||
// * `MAX_ATTEMPTS_WIFI_CONNECTION` (default 20) until it get connected. If
|
||||
// it
|
||||
// * does not happen, an error `ERROR_UNABLE_TO_CONNECT` is thrown.
|
||||
// *
|
||||
// */
|
||||
// bool tryConnectToWifi(const char *ssid, const char *password);
|
||||
|
||||
/**
|
||||
* Check if connection is established using `WiFi.status() == WL_CONNECTED`
|
||||
*
|
||||
*/
|
||||
bool isConnected();
|
||||
|
||||
std::vector<std::string> split(std::string s, std::string delimiter);
|
||||
|
||||
private:
|
||||
SerialWrite *serWriteCallback = NULL;
|
||||
OnImprovError *onImproErrorCallback = NULL;
|
||||
OnImprovConnected *onImprovConnectedCallback = NULL;
|
||||
CustomConnectWiFi *customConnectWiFiCallback = NULL;
|
||||
CustomScanWiFi *customScanWiFiCallback = NULL;
|
||||
CustomIsConnected *customIsConnectedCallback = NULL;
|
||||
CustomGetLocalIpCallback *customGetLocalIpCallback = NULL;
|
||||
};
|
||||
|
||||
#endif /* COMPONENTS_IMPROV_WIFI_INCLUDE_IMPROVWIFI_H_ */
|
||||
42
components/improv_wifi/priv_include/improv_wrapper.h
Normal file
42
components/improv_wifi/priv_include/improv_wrapper.h
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* improv_wrapper.h
|
||||
*
|
||||
* Created on: Apr 29, 2024
|
||||
* Author: karl
|
||||
*/
|
||||
|
||||
#ifndef COMPONENTS_IMPROV_WIFI_INCLUDE_IMPROV_WRAPPER_H_
|
||||
#define COMPONENTS_IMPROV_WIFI_INCLUDE_IMPROV_WRAPPER_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
#include "improvWifi.h"
|
||||
extern "C" {
|
||||
#else
|
||||
enum ChipFamily_e {
|
||||
CF_ESP32,
|
||||
CF_ESP32_C3,
|
||||
CF_ESP32_S2,
|
||||
CF_ESP32_S3,
|
||||
CF_ESP8266
|
||||
};
|
||||
#endif
|
||||
|
||||
void improv_wifi_create(void);
|
||||
void improv_wifi_destroy(void);
|
||||
int improv_wifi_handle_serial(const uint8_t *data, size_t length);
|
||||
void improv_wifi_set_device_info(uint8_t chipFamily, const char *firmwareName,
|
||||
const char *firmwareVersion,
|
||||
const char *deviceName, const char *deviceUrl);
|
||||
void improv_wifi_serialWrite(void *cb);
|
||||
void improv_wifi_onImprovError(void *onImprovErrorCb);
|
||||
void improv_wifi_onImprovConnected(void *onImprovConnectedCb);
|
||||
void improv_wifi_setCustomConnectWiFi(void *setCustomConnectWiFiCb);
|
||||
void improv_wifi_setCustomScanWiFi(void *setCustomScanWiFiCb);
|
||||
void improv_wifi_setCustomIsConnected(void *setCustomIsConnected);
|
||||
void improv_wifi_setCustomGetLocalIpCallback(void *getLocalIpCallback);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* COMPONENTS_IMPROV_WIFI_INCLUDE_IMPROV_WRAPPER_H_ */
|
||||
249
components/improv_wifi/wifi_provisioning.c
Normal file
249
components/improv_wifi/wifi_provisioning.c
Normal file
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* wifi_provisioning.c
|
||||
*
|
||||
* Created on: Apr 28, 2024
|
||||
* Author: karl
|
||||
*/
|
||||
|
||||
#include "wifi_provisioning.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "driver/uart.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "freertos/task.h"
|
||||
#include "improv_wrapper.h"
|
||||
#include "wifi_interface.h"
|
||||
|
||||
#define TAG "IMPROV"
|
||||
|
||||
#define RD_BUF_SIZE (UART_FIFO_LEN)
|
||||
#define PATTERN_CHR_NUM (3)
|
||||
|
||||
static TaskHandle_t t_improv_task = NULL;
|
||||
|
||||
static const int uart_buffer_size = 2 * RD_BUF_SIZE;
|
||||
static QueueHandle_t uart0_queue;
|
||||
|
||||
void uart_event_handler(void) {
|
||||
uart_event_t event;
|
||||
uint8_t dtmp[RD_BUF_SIZE];
|
||||
size_t buffered_size;
|
||||
|
||||
// Waiting for UART event.
|
||||
if (xQueueReceive(uart0_queue, (void *)&event, (TickType_t)portMAX_DELAY)) {
|
||||
bzero(dtmp, RD_BUF_SIZE);
|
||||
// ESP_LOGI(TAG, "uart[%d] event:", UART_NUM_0);
|
||||
switch (event.type) {
|
||||
// Event of UART receving data
|
||||
/*We'd better handler data event fast, there would be much more data
|
||||
events than other types of events. If we take too much time on data event,
|
||||
the queue might be full.*/
|
||||
case UART_DATA:
|
||||
// ESP_LOGI(TAG, "[UART DATA]: %d", event.size);
|
||||
|
||||
uart_read_bytes(UART_NUM_0, dtmp, event.size, portMAX_DELAY);
|
||||
// ESP_LOGI(TAG, "[DATA EVT]:");
|
||||
|
||||
improv_wifi_handle_serial(dtmp, event.size);
|
||||
break;
|
||||
// Event of HW FIFO overflow detected
|
||||
case UART_FIFO_OVF:
|
||||
// ESP_LOGI(TAG, "hw fifo overflow");
|
||||
|
||||
// If fifo overflow happened, you should consider adding flow control
|
||||
// for your application. The ISR has already reset the rx FIFO, As an
|
||||
// example, we directly flush the rx buffer here in order to read more
|
||||
// data.
|
||||
uart_flush_input(UART_NUM_0);
|
||||
xQueueReset(uart0_queue);
|
||||
break;
|
||||
// Event of UART ring buffer full
|
||||
case UART_BUFFER_FULL:
|
||||
// ESP_LOGI(TAG, "ring buffer full");
|
||||
// If buffer full happened, you should consider increasing your buffer
|
||||
// size As an example, we directly flush the rx buffer here in order to
|
||||
// read more data.
|
||||
uart_flush_input(UART_NUM_0);
|
||||
xQueueReset(uart0_queue);
|
||||
break;
|
||||
// Others
|
||||
default:
|
||||
// ESP_LOGI(TAG, "uart event type: %d", event.type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void improv_task(void *pvParameters) {
|
||||
while (1) {
|
||||
uart_event_handler();
|
||||
}
|
||||
}
|
||||
|
||||
void uart_write(const unsigned char *txData, int length) {
|
||||
uart_write_bytes(UART_NUM_0, txData, length);
|
||||
}
|
||||
|
||||
void improv_wifi_scan(unsigned char *scanResponse, int bufLen,
|
||||
uint16_t *count) {
|
||||
uint16_t number = 16;
|
||||
wifi_ap_record_t ap_info[16];
|
||||
|
||||
memset(ap_info, 0, sizeof(ap_info));
|
||||
|
||||
if (esp_wifi_scan_start(NULL, true) == ESP_ERR_WIFI_STATE) {
|
||||
wifi_ap_record_t ap_info_tmp;
|
||||
|
||||
do {
|
||||
esp_wifi_disconnect();
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
} while (esp_wifi_sta_get_ap_info(&ap_info_tmp) !=
|
||||
ESP_ERR_WIFI_NOT_CONNECT);
|
||||
|
||||
esp_wifi_scan_start(NULL, true);
|
||||
}
|
||||
// ESP_LOGI(TAG, "Max AP number ap_info can hold = %u", number);
|
||||
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_records(&number, ap_info));
|
||||
ESP_ERROR_CHECK(esp_wifi_scan_get_ap_num(count));
|
||||
// ESP_LOGI(TAG, "Total APs scanned = %u, actual AP number ap_info holds =
|
||||
// %u",
|
||||
// *count, number);
|
||||
|
||||
scanResponse[0] = 0;
|
||||
for (int i = 0; i < number; i++) {
|
||||
char rssiStr[8] = {
|
||||
0,
|
||||
};
|
||||
char cipherStr[8] = {
|
||||
0,
|
||||
};
|
||||
uint16_t neededLen;
|
||||
|
||||
itoa(ap_info[i].rssi, rssiStr, 10);
|
||||
if (ap_info[i].authmode != WIFI_AUTH_OPEN) {
|
||||
strcat(cipherStr, "YES");
|
||||
} else {
|
||||
strcat(cipherStr, "NO");
|
||||
}
|
||||
neededLen = strlen((const char *)ap_info[i].ssid) + strlen(rssiStr) +
|
||||
strlen(cipherStr) + 3;
|
||||
|
||||
if ((bufLen - neededLen) > 0) {
|
||||
strcat((char *)scanResponse, (char *)ap_info[i].ssid);
|
||||
strcat((char *)scanResponse, (char *)",");
|
||||
strcat((char *)scanResponse, (char *)rssiStr);
|
||||
strcat((char *)scanResponse, (char *)",");
|
||||
strcat((char *)scanResponse, (char *)cipherStr);
|
||||
strcat((char *)scanResponse, (char *)"\n");
|
||||
|
||||
bufLen -= neededLen;
|
||||
}
|
||||
}
|
||||
|
||||
// ESP_LOGI(TAG, "APs \t\t%s", scanResponse);
|
||||
}
|
||||
|
||||
bool improv_wifi_connect(const char *ssid, const char *password) {
|
||||
uint8_t count = 0;
|
||||
wifi_ap_record_t apRec;
|
||||
esp_err_t err;
|
||||
|
||||
while ((err = esp_wifi_sta_get_ap_info(&apRec)) != ESP_ERR_WIFI_NOT_CONNECT) {
|
||||
esp_wifi_disconnect();
|
||||
vTaskDelay(pdMS_TO_TICKS(100));
|
||||
}
|
||||
|
||||
wifi_config_t wifi_config;
|
||||
ESP_ERROR_CHECK(esp_wifi_get_config(WIFI_IF_STA, &wifi_config));
|
||||
strcpy((char *)wifi_config.sta.ssid, ssid);
|
||||
strcpy((char *)wifi_config.sta.password, password);
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||
|
||||
esp_wifi_connect();
|
||||
while (esp_wifi_sta_get_ap_info(&apRec) != ESP_OK) {
|
||||
vTaskDelay(pdMS_TO_TICKS(500));
|
||||
if (count > 20) {
|
||||
esp_wifi_disconnect();
|
||||
return false;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool improv_wifi_is_connected(void) {
|
||||
wifi_ap_record_t apRec;
|
||||
|
||||
if (esp_wifi_sta_get_ap_info(&apRec) == ESP_OK) {
|
||||
// printf("connected\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// printf("NOT connected\n");
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void improv_wifi_get_local_ip(uint8_t *address) {
|
||||
esp_netif_ip_info_t ip_info;
|
||||
|
||||
// TODO: find a better way to do this
|
||||
do {
|
||||
esp_netif_get_ip_info(get_current_netif(), &ip_info);
|
||||
vTaskDelay(pdMS_TO_TICKS(200));
|
||||
} while (ip_info.ip.addr == 0);
|
||||
|
||||
address[0] = ip_info.ip.addr >> 0;
|
||||
address[1] = ip_info.ip.addr >> 8;
|
||||
address[2] = ip_info.ip.addr >> 16;
|
||||
address[3] = ip_info.ip.addr >> 24;
|
||||
|
||||
// ESP_LOGI(TAG, "%d.%d.%d.%d", address[0], address[1], address[2],
|
||||
// address[3]);
|
||||
}
|
||||
|
||||
void improv_init(void) {
|
||||
uint8_t webPortStr[6] = {0};
|
||||
uint16_t webPort = CONFIG_WEB_PORT;
|
||||
uint8_t urlStr[26] = "http://{LOCAL_IPV4}:";
|
||||
|
||||
utoa(webPort, (char *)webPortStr, 10);
|
||||
strcat((char *)urlStr, (char *)webPortStr);
|
||||
|
||||
improv_wifi_create();
|
||||
improv_wifi_serialWrite(uart_write);
|
||||
improv_wifi_set_device_info(CF_ESP32, "esp32_snapclient", "0.0.3",
|
||||
"snapclient", (const char *)urlStr);
|
||||
|
||||
improv_wifi_setCustomConnectWiFi(improv_wifi_connect);
|
||||
improv_wifi_setCustomScanWiFi(improv_wifi_scan);
|
||||
improv_wifi_setCustomIsConnected(improv_wifi_is_connected);
|
||||
improv_wifi_setCustomGetLocalIpCallback(improv_wifi_get_local_ip);
|
||||
|
||||
// Set UART pins(TX: IO4, RX: IO5, RTS: IO18, CTS: IO19)
|
||||
// ESP_ERROR_CHECK(uart_set_pin(UART_NUM_0, 1, 3, -1, -1));
|
||||
|
||||
// Install UART driver using an event queue here
|
||||
ESP_ERROR_CHECK(uart_driver_install(UART_NUM_0, uart_buffer_size,
|
||||
uart_buffer_size, 10, &uart0_queue, 0));
|
||||
|
||||
xTaskCreatePinnedToCore(&improv_task, "improv", 4 * 1024, NULL, 4,
|
||||
&t_improv_task, tskNO_AFFINITY);
|
||||
}
|
||||
|
||||
void improv_deinit(void) {
|
||||
if (t_improv_task) {
|
||||
vTaskDelete(t_improv_task);
|
||||
uart_driver_delete(UART_NUM_0);
|
||||
|
||||
t_improv_task = NULL;
|
||||
}
|
||||
improv_wifi_destroy();
|
||||
}
|
||||
@@ -7,6 +7,10 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "snapcast.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define I2S_PORT I2S_NUM_0
|
||||
|
||||
// TODO: maybe calculate this dynamically based on chunk duration and buffer
|
||||
@@ -78,5 +82,7 @@ int32_t get_diff_to_server(int64_t *tDiff);
|
||||
int32_t server_now(int64_t *sNow, int64_t *diff2Server);
|
||||
|
||||
int32_t pcm_chunk_queue_msg_waiting(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // __PLAYER_H__
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#ifndef __SNAPCAST_H__
|
||||
#define __SNAPCAST_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
@@ -107,5 +111,8 @@ typedef struct time_message {
|
||||
int time_message_serialize(time_message_t *msg, char *data, uint32_t size);
|
||||
int time_message_deserialize(time_message_t *msg, const char *data,
|
||||
uint32_t size);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __SNAPCAST_H__
|
||||
|
||||
@@ -108,10 +108,12 @@ static bool i2sEnabled = false;
|
||||
*
|
||||
*/
|
||||
esp_err_t my_i2s_channel_disable(i2s_chan_handle_t handle) {
|
||||
if (i2sEnabled == true) {
|
||||
i2sEnabled = false;
|
||||
if (tx_chan != NULL) {
|
||||
if (i2sEnabled == true) {
|
||||
i2sEnabled = false;
|
||||
|
||||
return i2s_channel_disable(handle);
|
||||
return i2s_channel_disable(handle);
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
@@ -121,10 +123,12 @@ esp_err_t my_i2s_channel_disable(i2s_chan_handle_t handle) {
|
||||
*
|
||||
*/
|
||||
esp_err_t my_i2s_channel_enable(i2s_chan_handle_t handle) {
|
||||
if (i2sEnabled == false) {
|
||||
i2sEnabled = true;
|
||||
if (tx_chan != NULL) {
|
||||
if (i2sEnabled == false) {
|
||||
i2sEnabled = true;
|
||||
|
||||
return i2s_channel_enable(handle);
|
||||
return i2s_channel_enable(handle);
|
||||
}
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
@@ -142,7 +146,6 @@ static esp_err_t player_setup_i2s(i2s_port_t i2sNum,
|
||||
// works for all decoders. We set it to 100 so
|
||||
// there will be free space for sample stuffing in each round
|
||||
i2sDmaBufMaxLen = 100;
|
||||
|
||||
#else
|
||||
int fi2s_clk;
|
||||
const int __dmaBufMaxLen = 1024;
|
||||
@@ -199,6 +202,9 @@ static esp_err_t player_setup_i2s(i2s_port_t i2sNum,
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_LOGI(TAG, "player_setup_i2s: dma_buf_len is %ld, dma_buf_count is %ld",
|
||||
i2sDmaBufMaxLen, i2sDmaBufCnt);
|
||||
|
||||
if (tx_chan) {
|
||||
my_i2s_channel_disable(tx_chan);
|
||||
i2s_del_channel(tx_chan);
|
||||
@@ -240,8 +246,13 @@ static esp_err_t player_setup_i2s(i2s_port_t i2sNum,
|
||||
};
|
||||
i2s_std_config_t tx_std_cfg = {
|
||||
.clk_cfg = i2s_clkcfg,
|
||||
#if CONFIG_I2S_USE_MSB_FORMAT
|
||||
.slot_cfg =
|
||||
I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(bits, I2S_SLOT_MODE_STEREO),
|
||||
I2S_STD_MSB_SLOT_DEFAULT_CONFIG(setting->bits, I2S_SLOT_MODE_STEREO),
|
||||
#else
|
||||
.slot_cfg = I2S_STD_PHILIPS_SLOT_DEFAULT_CONFIG(setting->bits,
|
||||
I2S_SLOT_MODE_STEREO),
|
||||
#endif
|
||||
.gpio_cfg =
|
||||
{
|
||||
.mclk = pin_config0.mck_io_num,
|
||||
@@ -251,19 +262,31 @@ static esp_err_t player_setup_i2s(i2s_port_t i2sNum,
|
||||
.din = pin_config0.data_in_num,
|
||||
.invert_flags =
|
||||
{
|
||||
#if CONFIG_INVERT_MCLK_LEVEL
|
||||
.mclk_inv = true,
|
||||
|
||||
#else
|
||||
.mclk_inv = false,
|
||||
#endif
|
||||
|
||||
#if CONFIG_INVERT_BCLK_LEVEL
|
||||
.bclk_inv = true,
|
||||
#else
|
||||
.bclk_inv = false,
|
||||
#endif
|
||||
|
||||
#if CONFIG_INVERT_WORD_SELECT_LEVEL
|
||||
.ws_inv = true,
|
||||
#else
|
||||
.ws_inv = false,
|
||||
#endif
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
ESP_ERROR_CHECK(i2s_channel_init_std_mode(tx_chan, &tx_std_cfg));
|
||||
|
||||
ESP_LOGI(TAG,
|
||||
"player_setup_i2s: dma_buf_len is %ld, dma_buf_count is %ld, sample "
|
||||
"rate: %ld",
|
||||
i2sDmaBufMaxLen, i2sDmaBufCnt, setting->sr);
|
||||
// my_i2s_channel_enable(tx_chan);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -383,8 +406,6 @@ int init_player(void) {
|
||||
|
||||
tg0_timer_init();
|
||||
|
||||
ESP_LOGI(TAG, "test");
|
||||
|
||||
if (playerTaskHandle == NULL) {
|
||||
ESP_LOGI(TAG, "Start player_task");
|
||||
|
||||
@@ -445,15 +466,6 @@ int32_t player_latency_insert(int64_t newValue) {
|
||||
// ESP_LOGI(TAG, "(not full) latency median: %lldus", medianValue);
|
||||
// }
|
||||
|
||||
#if LATENCY_MEDIAN_age_DIVISOR
|
||||
// ESP_LOGI(TAG, "actual latency median: %lldus", medianValue);
|
||||
// medianValue = MEDIANFILTER_get_median(&latencyMedianFilter,
|
||||
// ceil((float)LATENCY_MEDIAN_FILTER_LEN /
|
||||
// (float)LATENCY_MEDIAN_age_DIVISOR));
|
||||
medianValue = MEDIANFILTER_get_median(&latencyMedianFilter, 32);
|
||||
// ESP_LOGI(TAG, "age latency median: %lldus", medianValue);
|
||||
#endif
|
||||
|
||||
latencyToServer = medianValue;
|
||||
|
||||
xSemaphoreGive(latencyBufSemaphoreHandle);
|
||||
@@ -1114,13 +1126,10 @@ int32_t insert_pcm_chunk(pcm_chunk_message_t *pcmChunk) {
|
||||
|
||||
// if (xQueueSend(pcmChkQHdl, &pcmChunk, pdMS_TO_TICKS(10)) != pdTRUE) {
|
||||
if (xQueueSend(pcmChkQHdl, &pcmChunk, pdMS_TO_TICKS(1)) != pdTRUE) {
|
||||
// if (xQueueSend(pcmChkQHdl, &pcmChunk, portMAX_DELAY) != pdTRUE) {
|
||||
ESP_LOGW(TAG, "send: pcmChunkQueue full, messages waiting %d",
|
||||
uxQueueMessagesWaiting(pcmChkQHdl));
|
||||
|
||||
free_pcm_chunk(pcmChunk);
|
||||
} else {
|
||||
// ESP_LOGI(TAG, "PCM chunk inserted");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1411,6 +1420,37 @@ static void player_task(void *pvParameters) {
|
||||
// get actual age after alarm
|
||||
age = (int64_t)timer_val - (-age);
|
||||
|
||||
// check if we need to write remaining data
|
||||
if (size != 0) {
|
||||
do {
|
||||
written = 0;
|
||||
if (i2s_custom_write(I2S_NUM_0, p_payload, (size_t)size, &written,
|
||||
portMAX_DELAY) != ESP_OK) {
|
||||
ESP_LOGE(TAG, "i2s_playback_task: I2S write error");
|
||||
}
|
||||
if (written < size) {
|
||||
ESP_LOGE(TAG,
|
||||
"i2s_playback_task: I2S didn't "
|
||||
"write all data");
|
||||
}
|
||||
size -= written;
|
||||
p_payload += written;
|
||||
|
||||
if (size == 0) {
|
||||
if (fragment->nextFragment != NULL) {
|
||||
fragment = fragment->nextFragment;
|
||||
p_payload = fragment->payload;
|
||||
size = fragment->size;
|
||||
} else {
|
||||
free_pcm_chunk(chnk);
|
||||
chnk = NULL;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
} while (1);
|
||||
}
|
||||
|
||||
initialSync = 1;
|
||||
|
||||
// TODO: use a timer to un-mute non blocking
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#ifndef _NET_FUNCTIONS_H_
|
||||
#define _NET_FUNCTIONS_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "mdns.h"
|
||||
|
||||
#define SNTP_TIMEZONE CONFIG_SNTP_TIMEZONE
|
||||
@@ -13,4 +17,8 @@ uint32_t find_mdns_service(const char* service_name, const char* proto);
|
||||
|
||||
void set_time_from_sntp(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _NET_FUNCTIONS_H_ */
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
#ifndef __UI_HTTP_SERVER_H__
|
||||
#define __UI_HTTP_SERVER_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void init_http_server_task(char *key);
|
||||
|
||||
typedef struct {
|
||||
@@ -11,4 +15,8 @@ typedef struct {
|
||||
float gain_3;
|
||||
} URL_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // __UI_HTTP_SERVER_H__
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
idf_component_register(SRCS "wifi_interface.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES wifi_provisioning esp_event esp_wifi esp_hw_support)
|
||||
REQUIRES wifi_provisioning esp_event esp_wifi esp_hw_support nvs_flash improv_wifi)
|
||||
|
||||
@@ -3,21 +3,7 @@ menu "Wifi Configuration"
|
||||
bool "enable WiFi provisioning"
|
||||
default n
|
||||
help
|
||||
Enable WiFi provisioning so espressif APP can be used to provison WiFi credentials
|
||||
|
||||
config WIFI_PROVISIONING_SSID
|
||||
string "WiFi provisioning SSID"
|
||||
default "prov_snapclient"
|
||||
depends on ENABLE_WIFI_PROVISIONING
|
||||
help
|
||||
SSID (network name) to use for provisioning access point. Shouldn't be longer than 20 characters.
|
||||
|
||||
config WIFI_PROVISIONING_PASSWORD
|
||||
string "WiFi provisioning password"
|
||||
default "12345678"
|
||||
depends on ENABLE_WIFI_PROVISIONING
|
||||
help
|
||||
WiFi password (WPA or WPA2) to use for provisioning access point
|
||||
Enable WiFi provisioning through improv WiFi (https://github.com/improv-wifi), try it using https://web.esphome.io/
|
||||
|
||||
config WIFI_SSID
|
||||
string "WiFi SSID"
|
||||
@@ -34,7 +20,7 @@ menu "Wifi Configuration"
|
||||
WiFi password (WPA or WPA2) for the example to use.
|
||||
|
||||
config WIFI_MAXIMUM_RETRY
|
||||
int "Maximum retry"
|
||||
int "Maximum connection retry"
|
||||
default 5
|
||||
help
|
||||
Set the Maximum retry to avoid station reconnecting to the AP unlimited when the AP is really inexistent.
|
||||
|
||||
@@ -10,33 +10,59 @@
|
||||
#include "esp_event.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_mac.h"
|
||||
#include "esp_timer.h"
|
||||
#include "esp_wifi.h"
|
||||
#include "nvs_flash.h"
|
||||
|
||||
#if ENABLE_WIFI_PROVISIONING
|
||||
#include <string.h> // for memcpy
|
||||
#include <wifi_provisioning/manager.h>
|
||||
#include <wifi_provisioning/scheme_softap.h>
|
||||
#endif
|
||||
|
||||
#if ENABLE_WIFI_PROVISIONING
|
||||
static const char *provPwd = CONFIG_WIFI_PROVISIONING_PASSWORD;
|
||||
static const char *provSsid = CONFIG_WIFI_PROVISIONING_SSID;
|
||||
#include "wifi_provisioning.h"
|
||||
#endif
|
||||
|
||||
static const char *TAG = "WIFI";
|
||||
|
||||
static void reset_reason_timer_counter_cb(void *);
|
||||
|
||||
static char mac_address[18];
|
||||
|
||||
EventGroupHandle_t s_wifi_event_group;
|
||||
|
||||
static int s_retry_num = 0;
|
||||
static wifi_config_t wifi_config;
|
||||
|
||||
static esp_netif_t *esp_wifi_netif = NULL;
|
||||
|
||||
/* FreeRTOS event group to signal when we are connected & ready to make a
|
||||
* request */
|
||||
// static EventGroupHandle_t wifi_event_group;
|
||||
#if ENABLE_WIFI_PROVISIONING
|
||||
static esp_timer_handle_t resetReasonTimerHandle = NULL;
|
||||
static const esp_timer_create_args_t resetReasonTimerArgs = {
|
||||
.callback = &reset_reason_timer_counter_cb,
|
||||
.dispatch_method = ESP_TIMER_TASK,
|
||||
.name = "rstCnt",
|
||||
.skip_unhandled_events = false};
|
||||
|
||||
static uint8_t resetReasonCounter = 0;
|
||||
|
||||
static void reset_reason_timer_counter_cb(void *args) {
|
||||
nvs_handle_t nvs_handle;
|
||||
esp_err_t err = nvs_open("storage", NVS_READWRITE, &nvs_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Error (%s) opening NVS handle!", __func__,
|
||||
esp_err_to_name(err));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "resetting POR reset counter ...");
|
||||
|
||||
resetReasonCounter = 0;
|
||||
|
||||
err |= nvs_set_u8(nvs_handle, "restart_counter", resetReasonCounter);
|
||||
err |= nvs_commit(nvs_handle);
|
||||
ESP_LOGI(TAG, "%s", (err != ESP_OK) ? "Failed!" : "Done");
|
||||
|
||||
nvs_close(nvs_handle);
|
||||
}
|
||||
|
||||
esp_timer_delete(resetReasonTimerHandle);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* The event group allows multiple bits for each event,
|
||||
but we only care about one event - are we connected
|
||||
@@ -65,61 +91,9 @@ static void event_handler(void *arg, esp_event_base_t event_base, int event_id,
|
||||
xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
|
||||
}
|
||||
ESP_LOGI(TAG, "connect to the AP fail");
|
||||
} else {
|
||||
#if ENABLE_WIFI_PROVISIONING
|
||||
if (event_base == WIFI_PROV_EVENT) {
|
||||
switch (event_id) {
|
||||
case WIFI_PROV_START:
|
||||
ESP_LOGI(TAG, "Provisioning started");
|
||||
break;
|
||||
case WIFI_PROV_CRED_RECV: {
|
||||
wifi_sta_config_t *wifi_sta_cfg = (wifi_sta_config_t *)event_data;
|
||||
ESP_LOGI(TAG,
|
||||
"Received Wi-Fi credentials"
|
||||
"\n\tSSID : %s\n\tPassword : %s",
|
||||
(const char *)wifi_sta_cfg->ssid,
|
||||
(const char *)wifi_sta_cfg->password);
|
||||
memcpy(&(wifi_config.sta), wifi_sta_cfg, sizeof(wifi_sta_config_t));
|
||||
break;
|
||||
}
|
||||
case WIFI_PROV_CRED_FAIL: {
|
||||
wifi_prov_sta_fail_reason_t *reason =
|
||||
(wifi_prov_sta_fail_reason_t *)event_data;
|
||||
ESP_LOGE(TAG,
|
||||
"Provisioning failed!\n\tReason : %s"
|
||||
"\n\tPlease reset to factory and retry provisioning",
|
||||
(*reason == WIFI_PROV_STA_AUTH_ERROR)
|
||||
? "Wi-Fi station authentication failed"
|
||||
: "Wi-Fi access-point not found");
|
||||
break;
|
||||
}
|
||||
case WIFI_PROV_CRED_SUCCESS:
|
||||
ESP_LOGI(TAG, "Provisioning successful");
|
||||
break;
|
||||
case WIFI_PROV_END:
|
||||
/* De-initialize manager once provisioning is finished */
|
||||
ESP_LOGI(TAG, "Provisioning end");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_WIFI_PROVISIONING
|
||||
static void get_device_service_name(char *service_name, size_t max) {
|
||||
uint8_t eth_mac[6];
|
||||
const char *ssid_prefix = provSsid;
|
||||
|
||||
esp_wifi_get_mac(WIFI_IF_STA, eth_mac);
|
||||
|
||||
snprintf(service_name, max, "%s_%02X%02X%02X", ssid_prefix, eth_mac[3],
|
||||
eth_mac[4], eth_mac[5]);
|
||||
}
|
||||
#endif
|
||||
|
||||
void wifi_init(void) {
|
||||
s_wifi_event_group = xEventGroupCreate();
|
||||
|
||||
@@ -132,121 +106,83 @@ void wifi_init(void) {
|
||||
ESP_ERROR_CHECK(
|
||||
esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP,
|
||||
(esp_event_handler_t)&event_handler, NULL));
|
||||
#if ENABLE_WIFI_PROVISIONING
|
||||
ESP_ERROR_CHECK(esp_event_handler_register(WIFI_PROV_EVENT, ESP_EVENT_ANY_ID,
|
||||
&event_handler, NULL));
|
||||
#endif
|
||||
|
||||
esp_wifi_netif = esp_netif_create_default_wifi_sta();
|
||||
#if ENABLE_WIFI_PROVISIONING
|
||||
esp_netif_create_default_wifi_ap();
|
||||
#endif
|
||||
|
||||
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
|
||||
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
|
||||
|
||||
// esp_wifi_set_bandwidth (WIFI_IF_STA, WIFI_BW_HT20);
|
||||
esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40);
|
||||
|
||||
esp_wifi_set_protocol(
|
||||
WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G | WIFI_PROTOCOL_11N);
|
||||
// esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B | WIFI_PROTOCOL_11G);
|
||||
// esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B);
|
||||
|
||||
// esp_wifi_set_ps(WIFI_PS_MIN_MODEM);
|
||||
// esp_wifi_set_ps(WIFI_PS_NONE);
|
||||
|
||||
#if ENABLE_WIFI_PROVISIONING
|
||||
// Configuration for the provisioning manager
|
||||
wifi_prov_mgr_config_t config = {
|
||||
.scheme = wifi_prov_scheme_softap,
|
||||
.scheme_event_handler = WIFI_PROV_EVENT_HANDLER_NONE};
|
||||
esp_reset_reason_t resetReason = esp_reset_reason();
|
||||
ESP_LOGI(TAG, "reset reason was: %d", resetReason);
|
||||
esp_timer_create(&resetReasonTimerArgs, &resetReasonTimerHandle);
|
||||
esp_timer_start_once(resetReasonTimerHandle, 5000000);
|
||||
if (resetReason == ESP_RST_POWERON) {
|
||||
nvs_handle_t nvs_handle;
|
||||
esp_err_t err = nvs_open("storage", NVS_READWRITE, &nvs_handle);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "%s: Error (%s) opening NVS handle!", __func__,
|
||||
esp_err_to_name(err));
|
||||
} else {
|
||||
ESP_LOGI(TAG, "get POR reset counter ...");
|
||||
err |= nvs_get_u8(nvs_handle, "restart_counter", &resetReasonCounter);
|
||||
|
||||
// Initialize provisioning manager with the
|
||||
// configuration parameters set above
|
||||
ESP_ERROR_CHECK(wifi_prov_mgr_init(config));
|
||||
ESP_LOGI(TAG, "reset counter %d", resetReasonCounter);
|
||||
|
||||
bool provisioned = false;
|
||||
/* Let's find out if the device is provisioned */
|
||||
ESP_ERROR_CHECK(wifi_prov_mgr_is_provisioned(&provisioned));
|
||||
resetReasonCounter++;
|
||||
|
||||
/* If device is not yet provisioned start provisioning service */
|
||||
if (!provisioned) {
|
||||
ESP_LOGI(TAG, "Starting provisioning");
|
||||
if (resetReasonCounter > 3) {
|
||||
ESP_LOGW(TAG, "resetting WIFI credentials!");
|
||||
|
||||
// Wi-Fi SSID when scheme is wifi_prov_scheme_softap
|
||||
char service_name[27];
|
||||
get_device_service_name(service_name, sizeof(service_name));
|
||||
resetReasonCounter = 0;
|
||||
|
||||
/* What is the security level that we want (0 or 1):
|
||||
* - WIFI_PROV_SECURITY_0 is simply plain text communication.
|
||||
* - WIFI_PROV_SECURITY_1 is secure communication which consists of
|
||||
* secure handshake using X25519 key exchange and proof of possession
|
||||
* (pop) and AES-CTR for encryption/decryption of messages.
|
||||
*/
|
||||
wifi_prov_security_t security = WIFI_PROV_SECURITY_1;
|
||||
esp_wifi_restore();
|
||||
// esp_wifi_set_bandwidth (WIFI_IF_STA, WIFI_BW_HT20);
|
||||
esp_wifi_set_bandwidth(WIFI_IF_STA, WIFI_BW_HT40);
|
||||
esp_wifi_set_protocol(WIFI_IF_STA, WIFI_PROTOCOL_11B |
|
||||
WIFI_PROTOCOL_11G |
|
||||
WIFI_PROTOCOL_11N);
|
||||
|
||||
/* Do we want a proof-of-possession (ignored if Security 0 is selected):
|
||||
* - this should be a string with length > 0
|
||||
* - NULL if not used
|
||||
*/
|
||||
const char *pop = NULL; //"abcd1234";
|
||||
esp_timer_stop(resetReasonTimerHandle);
|
||||
esp_timer_delete(resetReasonTimerHandle);
|
||||
}
|
||||
|
||||
/* What is the service key (could be NULL)
|
||||
* This translates to :
|
||||
* - Wi-Fi password when scheme is wifi_prov_scheme_softap
|
||||
* - simply ignored when scheme is wifi_prov_scheme_ble
|
||||
*/
|
||||
const char *service_key = provPwd;
|
||||
err |= nvs_set_u8(nvs_handle, "restart_counter", resetReasonCounter);
|
||||
err |= nvs_commit(nvs_handle);
|
||||
ESP_LOGI(TAG, "%s", (err != ESP_OK) ? "Failed!" : "Done");
|
||||
|
||||
/* An optional endpoint that applications can create if they expect to
|
||||
* get some additional custom data during provisioning workflow.
|
||||
* The endpoint name can be anything of your choice.
|
||||
* This call must be made before starting the provisioning.
|
||||
*/
|
||||
// wifi_prov_mgr_endpoint_create("custom-data");
|
||||
/* Start provisioning service */
|
||||
ESP_ERROR_CHECK(wifi_prov_mgr_start_provisioning(
|
||||
security, pop, service_name, service_key));
|
||||
|
||||
/* The handler for the optional endpoint created above.
|
||||
* This call must be made after starting the provisioning, and only if
|
||||
* the endpoint has already been created above.
|
||||
*/
|
||||
// wifi_prov_mgr_endpoint_register("custom-data",
|
||||
// custom_prov_data_handler, NULL);
|
||||
|
||||
/* Uncomment the following to wait for the provisioning to finish and
|
||||
* then release the resources of the manager. Since in this case
|
||||
* de-initialization is triggered by the default event loop handler, we
|
||||
* don't need to call the following */
|
||||
wifi_prov_mgr_wait();
|
||||
wifi_prov_mgr_deinit();
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Already provisioned, starting Wi-Fi STA");
|
||||
|
||||
/* We don't need the manager as device is already provisioned,
|
||||
* so let's release it's resources */
|
||||
wifi_prov_mgr_deinit();
|
||||
|
||||
/* Start Wi-Fi station */
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
|
||||
wifi_config_t wifi_config;
|
||||
ESP_ERROR_CHECK(esp_wifi_get_config(WIFI_IF_STA, &wifi_config));
|
||||
wifi_config.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL;
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "wifi_init_sta finished.");
|
||||
nvs_close(nvs_handle);
|
||||
}
|
||||
}
|
||||
|
||||
/* Start Wi-Fi station */
|
||||
ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
|
||||
|
||||
wifi_config_t wifi_config;
|
||||
ESP_ERROR_CHECK(esp_wifi_get_config(WIFI_IF_STA, &wifi_config));
|
||||
wifi_config.sta.sort_method = WIFI_CONNECT_AP_BY_SIGNAL;
|
||||
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
|
||||
|
||||
ESP_ERROR_CHECK(esp_wifi_start());
|
||||
|
||||
ESP_LOGI(TAG, "Starting provisioning");
|
||||
|
||||
improv_init();
|
||||
#else
|
||||
wifi_config_t wifi_config = {
|
||||
.sta =
|
||||
{
|
||||
.ssid = WIFI_SSID,
|
||||
.password = WIFI_PASSWORD,
|
||||
.sort_method = WIFI_CONNECT_AP_BY_SIGNAL,
|
||||
.threshold.authmode = WIFI_AUTH_WPA2_PSK,
|
||||
.pmf_cfg = {.capable = true, .required = false},
|
||||
},
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
dependencies:
|
||||
espressif/esp-dsp:
|
||||
component_hash: fa7fe74305df6da25867437ebcd4213e047cbfc0556cf92067ab657fce537c6e
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=4.2'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.5.2
|
||||
espressif/mdns:
|
||||
component_hash: d36b265164be5139f92de993f08f5ecaa0de0c0acbf84deee1f10bb5902d04ff
|
||||
dependencies:
|
||||
- name: idf
|
||||
require: private
|
||||
version: '>=5.0'
|
||||
source:
|
||||
registry_url: https://components.espressif.com/
|
||||
type: service
|
||||
version: 1.4.3
|
||||
idf:
|
||||
source:
|
||||
type: idf
|
||||
version: 5.1.5
|
||||
direct_dependencies:
|
||||
- espressif/esp-dsp
|
||||
- espressif/mdns
|
||||
- idf
|
||||
manifest_hash: 01df6f188570b9e5362f7a00a294b1d3403de1f5ce8cbd848004d3bc88aa09a8
|
||||
target: esp32
|
||||
version: 2.0.0
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
idf_component_register(SRCS "main.c"
|
||||
INCLUDE_DIRS "."
|
||||
PRIV_REQUIRES esp_timer esp_wifi nvs_flash wifi_interface audio_board audio_hal audio_sal net_functions opus flac ota_server
|
||||
ui_http_server eth_interface
|
||||
ui_http_server improv_wifi eth_interface
|
||||
)
|
||||
|
||||
76
main/main.c
76
main/main.c
@@ -17,7 +17,8 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/event_groups.h"
|
||||
#include "freertos/task.h"
|
||||
#if CONFIG_SNAPCLIENT_ENABLE_ETHERNET
|
||||
#if CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET || \
|
||||
CONFIG_SNAPCLIENT_USE_SPI_ETHERNET
|
||||
#include "eth_interface.h"
|
||||
#endif
|
||||
|
||||
@@ -25,6 +26,8 @@
|
||||
#include "wifi_interface.h"
|
||||
|
||||
// Minimum ESP-IDF stuff only hardware abstraction stuff
|
||||
#include <wifi_provisioning.h>
|
||||
|
||||
#include "board.h"
|
||||
#include "es8388.h"
|
||||
#include "esp_netif.h"
|
||||
@@ -79,10 +82,11 @@ static FLAC__StreamDecoder *flacDecoder = NULL;
|
||||
const char *VERSION_STRING = "0.0.3";
|
||||
|
||||
#define HTTP_TASK_PRIORITY 9
|
||||
#define HTTP_TASK_CORE_ID tskNO_AFFINITY // 1 // tskNO_AFFINITY
|
||||
#define HTTP_TASK_CORE_ID tskNO_AFFINITY
|
||||
|
||||
#define OTA_TASK_PRIORITY 4
|
||||
#define OTA_TASK_PRIORITY 6
|
||||
#define OTA_TASK_CORE_ID tskNO_AFFINITY
|
||||
// 1 // tskNO_AFFINITY
|
||||
|
||||
TaskHandle_t t_ota_task = NULL;
|
||||
TaskHandle_t t_http_get_task = NULL;
|
||||
@@ -414,22 +418,6 @@ void error_callback(const FLAC__StreamDecoder *decoder,
|
||||
FLAC__StreamDecoderErrorStatusString[status]);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add one timeval to another.
|
||||
*/
|
||||
tv_t timeval_add(tv_t *a, tv_t *b) {
|
||||
tv_t result;
|
||||
|
||||
result.sec = a->sec + b->sec;
|
||||
result.usec = a->usec + b->usec;
|
||||
if (result.usec >= 1000000) {
|
||||
result.sec += 1;
|
||||
result.usec -= 1000000;
|
||||
}
|
||||
|
||||
return result;
|
||||
} // timeval_add
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
@@ -621,7 +609,8 @@ static void http_get_task(void *pvParameters) {
|
||||
char mac_address[18];
|
||||
uint8_t base_mac[6];
|
||||
// Get MAC address for WiFi station
|
||||
#if CONFIG_SNAPCLIENT_ENABLE_ETHERNET
|
||||
#if CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET || \
|
||||
CONFIG_SNAPCLIENT_USE_SPI_ETHERNET
|
||||
esp_read_mac(base_mac, ESP_MAC_ETH);
|
||||
#else
|
||||
esp_read_mac(base_mac, ESP_MAC_WIFI_STA);
|
||||
@@ -1749,8 +1738,6 @@ static void http_get_task(void *pvParameters) {
|
||||
}
|
||||
|
||||
if (codec == OPUS) {
|
||||
// ESP_LOGI(TAG, "OPUS not
|
||||
// mplemented yet"); return;
|
||||
uint16_t channels;
|
||||
uint32_t rate;
|
||||
uint16_t bits;
|
||||
@@ -2408,15 +2395,20 @@ void app_main(void) {
|
||||
ESP_ERROR_CHECK(ret);
|
||||
|
||||
esp_log_level_set("*", ESP_LOG_INFO);
|
||||
// esp_log_level_set("c_I2S", ESP_LOG_NONE);
|
||||
|
||||
// if enabled these cause a timer srv stack overflow
|
||||
esp_log_level_set("HEADPHONE", ESP_LOG_NONE);
|
||||
esp_log_level_set("gpio", ESP_LOG_NONE);
|
||||
esp_log_level_set("i2s_std", ESP_LOG_DEBUG);
|
||||
esp_log_level_set("i2s_common", ESP_LOG_DEBUG);
|
||||
esp_log_level_set("gpio", ESP_LOG_WARN);
|
||||
esp_log_level_set("uart", ESP_LOG_WARN);
|
||||
// esp_log_level_set("i2s_std", ESP_LOG_DEBUG);
|
||||
// esp_log_level_set("i2s_common", ESP_LOG_DEBUG);
|
||||
esp_log_level_set("wifi", ESP_LOG_WARN);
|
||||
esp_log_level_set("wifi_init", ESP_LOG_WARN);
|
||||
esp_log_level_set("wifi", ESP_LOG_WARN);
|
||||
esp_log_level_set("wifi_init", ESP_LOG_WARN);
|
||||
|
||||
#if CONFIG_SNAPCLIENT_ENABLE_ETHERNET
|
||||
#if CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET || \
|
||||
CONFIG_SNAPCLIENT_USE_SPI_ETHERNET
|
||||
// clang-format off
|
||||
// nINT/REFCLKO Function Select Configuration Strap
|
||||
// • When nINTSEL is floated or pulled to
|
||||
@@ -2516,9 +2508,35 @@ void app_main(void) {
|
||||
|
||||
// ESP_LOGI(TAG, "init player");
|
||||
init_player();
|
||||
// setup_ma120();
|
||||
|
||||
#if CONFIG_SNAPCLIENT_ENABLE_ETHERNET
|
||||
// ensure there is no noise from DAC
|
||||
{
|
||||
board_i2s_pin_t pin_config0;
|
||||
get_i2s_pins(I2S_NUM_0, &pin_config0);
|
||||
|
||||
gpio_config_t gpioCfg = {
|
||||
.pin_bit_mask =
|
||||
BIT64(pin_config0.mck_io_num) | BIT64(pin_config0.data_out_num) |
|
||||
BIT64(pin_config0.bck_io_num) | BIT64(pin_config0.ws_io_num),
|
||||
.mode = GPIO_MODE_OUTPUT,
|
||||
.pull_up_en = GPIO_PULLUP_DISABLE,
|
||||
.pull_down_en = GPIO_PULLDOWN_DISABLE,
|
||||
.intr_type = GPIO_INTR_DISABLE,
|
||||
};
|
||||
gpio_config(&gpioCfg);
|
||||
gpio_set_level(pin_config0.mck_io_num, 0);
|
||||
gpio_set_level(pin_config0.data_out_num, 0);
|
||||
gpio_set_level(pin_config0.bck_io_num, 0);
|
||||
gpio_set_level(pin_config0.ws_io_num, 0);
|
||||
|
||||
gpioCfg.pin_bit_mask = BIT64(pin_config0.data_in_num);
|
||||
gpioCfg.mode = GPIO_MODE_INPUT;
|
||||
gpioCfg.pull_up_en = GPIO_PULLUP_ENABLE;
|
||||
gpio_config(&gpioCfg);
|
||||
}
|
||||
|
||||
#if CONFIG_SNAPCLIENT_USE_INTERNAL_ETHERNET || \
|
||||
CONFIG_SNAPCLIENT_USE_SPI_ETHERNET
|
||||
eth_init();
|
||||
// pass "WIFI_STA_DEF", "WIFI_AP_DEF", "ETH_DEF"
|
||||
init_http_server_task("ETH_DEF");
|
||||
|
||||
1978
sdkconfig_PCM5102A
Normal file
1978
sdkconfig_PCM5102A
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
2038
sdkconfig_TAS5805M
Normal file
2038
sdkconfig_TAS5805M
Normal file
File diff suppressed because it is too large
Load Diff
1466
sdkconfig_adau1961
1466
sdkconfig_adau1961
File diff suppressed because it is too large
Load Diff
1393
sdkconfig_lyrat_v4.3
1393
sdkconfig_lyrat_v4.3
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user