Merge remote-tracking branch 'origin/master' into master-cmake

Conflicts:
	components/raop/raop.c
	components/raop/rtp.c
This commit is contained in:
Sebastien
2020-03-10 10:52:18 -04:00
13 changed files with 950 additions and 897 deletions

View File

@@ -1,51 +1,11 @@
cmake_minimum_required(VERSION 3.5)
set(EXTRA_COMPONENT_DIRS components/platform_console/app_recovery components/platform_console/app_squeezelite )
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
message(WARNING "Building RECOVERY")
message(STATUS "Building RECOVERY")
project(recovery)
set_property(TARGET recovery.elf PROPERTY RECOVERY_BUILD 0 )
set_property(TARGET recovery.elf PROPERTY RECOVERY_PREFIX app_recovery )
#
#message(WARNING "Building SQUEEZELITE")
#set(project_name squeezelite)
#__project(${project_name} C CXX ASM)
#
set(squeezelite_project_elf squeezelite.elf)
#
# # Create a dummy file to work around CMake requirement of having a source
# # file while adding an executable
set(squeezelite_project_elf_src ${CMAKE_BINARY_DIR}/squeezelite_project_elf_src.c)
add_custom_command(OUTPUT ${squeezelite_project_elf_src}
COMMAND ${CMAKE_COMMAND} -E touch ${squeezelite_project_elf_src}
VERBATIM)
add_custom_command(OUTPUT "${build_dir}/.squeezelite_bin_timestamp"
COMMAND echo ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${esptool_elf2image_args}
COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${esptool_elf2image_args}
-o "${build_dir}/squeezelite.bin" "squeezelite.elf"
COMMAND ${CMAKE_COMMAND} -E echo "Generated ${build_dir}/squeezelite.bin"
COMMAND ${CMAKE_COMMAND} -E md5sum "${build_dir}/squeezelite.bin" > "${build_dir}/.squeezelite_bin_timestamp"
VERBATIM
WORKING_DIRECTORY ${build_dir}
COMMENT "Generating binary image from built executable"
)
add_custom_target(_squeezelite_project_elf_src DEPENDS "${squeezelite_project_elf_src}" "${build_dir}/.squeezelite_bin_timestamp")
add_executable(${squeezelite_project_elf} "${squeezelite_project_elf_src}")
add_dependencies(${squeezelite_project_elf} _squeezelite_project_elf_src)
set_property(TARGET ${squeezelite_project_elf} PROPERTY RECOVERY_BUILD 0 )
set_property(TARGET ${squeezelite_project_elf} PROPERTY RECOVERY_PREFIX app_squeezelite)
idf_build_get_property(bca BUILD_COMPONENT_ALIASES)
target_link_libraries(${squeezelite_project_elf} ${bca})
set(squeezelite_mapfile "${CMAKE_BINARY_DIR}/squeezelite.map")
target_link_libraries(${squeezelite_project_elf} "-Wl,--cref -Wl,--Map=${squeezelite_mapfile}")
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES
"${squeezelite_mapfile}" "${squeezelite_project_elf_src}")
partition_table_get_partition_info(otaapp_offset "--partition-type app --partition-subtype ota_0" "offset")
esptool_py_flash_project_args(squeezelite ${otaapp_offset} ${build_dir}/squeezelite.bin FLASH_IN_PROJECT)
include(squeezelite.cmake)

View File

@@ -6,7 +6,21 @@ Works with the SqueezeAMP see [here](https://forums.slimdevices.com/showthread.p
Use the `squeezelite-esp32-SqueezeAmp-sdkconfig.defaults` configuration file.
### ESP32-A1S
Works with [ESP32-A1S](https://docs.ai-thinker.com/esp32-a1s) module that includes audio codec and headset output. You still need to use a demo board or an external amplifier if you want direct speaker connection.
Works with [ESP32-A1S](https://docs.ai-thinker.com/esp32-a1s) module that includes audio codec and headset output. You still need to use a demo board like [this](https://www.aliexpress.com/item/4000765857347.html?spm=2114.12010615.8148356.11.5d963cd0j669ns) or an external amplifier if you want direct speaker connection.
The board showed above has the following IO set
- amplifier: GPIO21
- key2: GPIO13, key3: GPIO19, key4: GPIO23, key5: GPIO18, key6: GPIO5 (to be confirmed width dipswitches)
- key1: not sure, something with GPIO36
- jack insertion: GPIO39 (inserted low)
- LED: GPIO22 (active low)
So a possible config would be
- set_GPIO: 21=amp,22=green:0,39=jack:0
- a button mapping:
```
[{"gpio":5,"normal":{"pressed":"ACTRLS_TOGGLE"}},{"gpio":18,"shifter_gpio":5,"normal":{"pressed":"ACTRLS_VOLUP"}, "shifted":{"pressed":"ACTRLS_NEXT"}}, {"gpio":23,"shifter_gpio":5,"normal":{"pressed":"ACTRLS_VOLDOWN"},"shifted":{"pressed":"ACTRLS_PREV"}}]
```
### ESP32-WROVER + I2S DAC
Squeezelite-esp32 requires esp32 chipset and 4MB PSRAM. ESP32-WROVER meets these requirements. To get an audio output an I2S DAC can be used. Cheap PCM5102 I2S DACs work others may also work. PCM5012 DACs can be hooked up via:
@@ -137,10 +151,14 @@ Where (all parameters are optionals except gpio)
- "shifted": action to take when a button is pressed/released and shifted (see above/below)
- "longshifted": action to take when a button is long-pressed/released and shifted (see above/below)
Where \<action\> is either the name of another configuration to load or one amongst
ACTRLS_NONE, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY,
ACTRLS_PAUSE, ACTRLS_STOP, ACTRLS_REW, ACTRLS_FWD, ACTRLS_PREV, ACTRLS_NEXT,
BCTRLS_PUSH, BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT
Where \<action\> is either the name of another configuration to load (remap) or one amongst
```
ACTRLS_NONE, ACTRLS_VOLUP, ACTRLS_VOLDOWN, ACTRLS_TOGGLE, ACTRLS_PLAY,
ACTRLS_PAUSE, ACTRLS_STOP, ACTRLS_REW, ACTRLS_FWD, ACTRLS_PREV, ACTRLS_NEXT,
BCTRLS_PUSH, BCTRLS_UP, BCTRLS_DOWN, BCTRLS_LEFT, BCTRLS_RIGHT,
KNOB_LEFT, KNOB_RIGHT, KNOB_PUSH
```
One you've created such a string, use it to fill a new NVS parameter with any name below 16(?) characters. You can have as many of these configs as you can. Then set the config parameter "actrls_config" with the name of your default config

View File

@@ -8,10 +8,4 @@ idf_component_register( SRCS
INCLUDE_DIRS .
REQUIRES nvs_flash
PRIV_REQUIRES console tools services spi_flash app_update platform_config vfs pthread wifi-manager platform_config codecs newlib )
#target_link_libraries(__idf_platform_console $<IF:${recovery_build}, ${build_dir}/esp-idf/app_recovery/libapp_recovery.a,${build_dir}/esp-idf/app_squeezelite/libapp_squeezelite.a > )
message($<TARGET_PROPERTY:RECOVERY_PREFIX>)
target_link_libraries(__idf_platform_console ${build_dir}/esp-idf/$<TARGET_PROPERTY:RECOVERY_PREFIX>/lib$<TARGET_PROPERTY:RECOVERY_PREFIX>.a )
#target_link_libraries(__idf_platform_console $<NOT ${recovery_build}:${build_dir}/esp-idf/app_squeezelite/libapp_squeezelite )

View File

@@ -437,6 +437,12 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
LOG_INFO("[%p]: received %s", ctx, method);
}
if ((buf = kd_lookup(headers, "Apple-Challenge")) != NULL) {
int n;
char *buf_pad, *p, *data_b64 = NULL, data[32];
LOG_INFO("[%p]: challenge %s", ctx, buf);
// try to re-acquire IP address if we were missing it
if (S_ADDR(ctx->host) == INADDR_ANY) {
S_ADDR(ctx->host) = get_localhost(NULL);

View File

@@ -163,7 +163,7 @@ void raop_sink_init(raop_cmd_vcb_t cmd_cb, raop_data_cb_t data_cb) {
free(sink_name_buffer);
}
LOG_INFO( "mdns hostname set to: [%s] with servicename %s", hostname, sink_name);
LOG_INFO( "mdns hostname for ip %s set to: [%s] with servicename %s", inet_ntoa(host), hostname, sink_name);
// create RAOP instance, latency is set by controller
uint8_t mac[6];

View File

@@ -38,7 +38,6 @@
#include <sys/stat.h>
#include <stdint.h>
#include <fcntl.h>
#include <assert.h>
#include "platform.h"
#include "rtp.h"
@@ -49,10 +48,12 @@
#ifdef WIN32
#include <openssl/aes.h>
#include "alac_wrapper.h"
#include "assert.h"
#define MSG_DONTWAIT 0
#else
#include "esp_pthread.h"
#include "esp_system.h"
#include "esp_assert.h"
#include <mbedtls/version.h>
#include <mbedtls/aes.h>
#include "alac_wrapper.h"

View File

@@ -23,12 +23,7 @@
#ifdef WIN32
#include <iphlpapi.h>
#else
/*
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netdb.h>
*/
#include "tcpip_adapter.h"
#include <ctype.h>
#endif
@@ -84,8 +79,26 @@ in_addr_t get_localhost(char **name)
}
else return INADDR_ANY;
#else
// missing platform here ...
return INADDR_ANY;
tcpip_adapter_ip_info_t ipInfo;
tcpip_adapter_if_t if_type = TCPIP_ADAPTER_IF_STA;
// then get IP address
tcpip_adapter_get_ip_info(if_type, &ipInfo);
// we might be in AP mode
if (ipInfo.ip.addr == INADDR_ANY) {
if_type = TCPIP_ADAPTER_IF_AP;
tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ipInfo);
}
// get hostname if required
if (name) {
const char *hostname;
tcpip_adapter_get_hostname(if_type, &hostname);
*name = strdup(hostname);
}
return ipInfo.ip.addr;
#endif
}

View File

@@ -191,7 +191,7 @@ void button_create(void *client, int gpio, int type, bool pull, int debounce, bu
if (n_buttons >= MAX_BUTTONS) return;
ESP_LOGI(TAG, "Creating button using GPIO %u, type %u, pull-up/down %u, long press %u shifter %u", gpio, type, pull, long_press, shifter_gpio);
ESP_LOGI(TAG, "Creating button using GPIO %u, type %u, pull-up/down %u, long press %u shifter %d", gpio, type, pull, long_press, shifter_gpio);
if (!n_buttons) {
button_evt_queue = xQueueCreate(BUTTON_QUEUE_LEN, sizeof(struct button_s));
@@ -209,7 +209,6 @@ void button_create(void *client, int gpio, int type, bool pull, int debounce, bu
buttons[n_buttons].debounce = debounce ? debounce: DEBOUNCE;
buttons[n_buttons].handler = handler;
buttons[n_buttons].long_press = long_press;
buttons[n_buttons].level = -1;
buttons[n_buttons].shifter_gpio = shifter_gpio;
buttons[n_buttons].type = type;
buttons[n_buttons].timer = xTimerCreate("buttonTimer", buttons[n_buttons].debounce / portTICK_RATE_MS, pdFALSE, (void *) &buttons[n_buttons], buttons_timer);
@@ -248,6 +247,9 @@ void button_create(void *client, int gpio, int type, bool pull, int debounce, bu
// nasty ESP32 bug: fire-up constantly INT on GPIO 36/39 if ADC1, AMP, Hall used which WiFi does when PS is activated
if (gpio == 36 || gpio == 39) gpio36_39_used = true;
// and initialize level ...
buttons[n_buttons].level = gpio_get_level(gpio);
gpio_isr_handler_add(gpio, gpio_isr_handler, (void*) &buttons[n_buttons]);
gpio_intr_enable(gpio);

View File

@@ -116,7 +116,8 @@ static void jack_handler_default(void *id, button_event_e event, button_press_e
*
*/
bool jack_inserted_svc (void) {
return button_is_pressed(jack.gpio, NULL);
if (jack.gpio != -1) return button_is_pressed(jack.gpio, NULL);
else return true;
}
/****************************************************************************************

View File

@@ -35,7 +35,7 @@
const static char TAG[] = "AC101";
#define SPKOUT_EN ((1 << 11) | (1 << 7))
#define SPKOUT_EN ((1 << 9) | (1 << 11) | (1 << 7) | (1 << 5))
#define EAROUT_EN ((1 << 11) | (1 << 12) | (1 << 13))
#define BIN(a,b,c,d) 0b##a##b##c##d
@@ -132,8 +132,8 @@ static bool init(int i2c_port_num, int i2s_num, i2s_config_t *i2s_config) {
//Path Configuration
i2c_write_reg(DAC_MXR_SRC, BIN(1000,1000,0000,0000)); // DAC from I2S
i2c_write_reg(DAC_DIG_CTRL, BIN(1000,0000,0000,0000)); // enable DAC
i2c_write_reg(OMIXER_DACA_CTRL, BIN(1111,0000,0000,000)); // enable DAC/Analogue (see note on offset removal and PA)
i2c_write_reg(OMIXER_DACA_CTRL, BIN(1100,0000,0000,000)); // enable DAC/Analogue (see note on offset removal and PA)
i2c_write_reg(OMIXER_DACA_CTRL, BIN(1111,0000,0000,0000)); // enable DAC/Analogue (see note on offset removal and PA)
i2c_write_reg(OMIXER_DACA_CTRL, BIN(1111,1111,0000,0000)); // this toggle is needed for headphone PA offset
#if ENABLE_ADC
i2c_write_reg(OMIXER_SR, BIN(0000,0001,0000,0010)); // source=DAC(R/L) (are DACR and DACL really inverted in bitmap?)
#else
@@ -149,8 +149,7 @@ static bool init(int i2c_port_num, int i2s_num, i2s_config_t *i2s_config) {
// enable earphone & speaker
i2c_write_reg(SPKOUT_CTRL, 0x0220);
i2c_write_reg(OMIXER_DACA_CTRL, 0xff00);
i2c_write_reg(HPOUT_CTRL, 0x3801);
i2c_write_reg(HPOUT_CTRL, 0xf801);
// set gain for speaker and earphone
ac101_set_spk_volume(100);
@@ -206,6 +205,7 @@ static void speaker(bool active) {
* headset
*/
static void headset(bool active) {
// there might be aneed to toggle OMIXER_DACA_CTRL 11:8, not sure
uint16_t value = i2c_read_reg(HPOUT_CTRL);
if (active) i2c_write_reg(HPOUT_CTRL, value | EAROUT_EN);
else i2c_write_reg(HPOUT_CTRL, value & ~EAROUT_EN);
@@ -284,14 +284,14 @@ static int ac101_get_spk_volume(void) {
* Set normalized (0..100) volume
*/
static void ac101_set_spk_volume(uint8_t volume) {
volume = max(volume, 0x1f);
volume = ((int) volume * 0x1f) / 100;
volume |= i2c_read_reg(SPKOUT_CTRL) & ~0x1f;
i2c_write_reg(SPKOUT_CTRL, volume);
uint16_t value = max(volume, 100);
value = ((int) value * 0x1f) / 100;
value |= i2c_read_reg(SPKOUT_CTRL) & ~0x1f;
i2c_write_reg(SPKOUT_CTRL, value);
}
/****************************************************************************************
* Get normalized (0..100) earphonz volume
* Get normalized (0..100) earphone volume
*/
static int ac101_get_earph_volume(void) {
return (((i2c_read_reg(HPOUT_CTRL) >> 4) & 0x3f) * 100) / 0x3f;
@@ -301,10 +301,10 @@ static int ac101_get_earph_volume(void) {
* Set normalized (0..100) earphone volume
*/
static void ac101_set_earph_volume(uint8_t volume) {
volume = max(volume, 0x3f);
volume = (((int) volume * 0x3f) / 100) << 4;
volume |= i2c_read_reg(HPOUT_CTRL) & ~(0x3f << 4);
i2c_write_reg(HPOUT_CTRL, volume);
uint16_t value = max(volume, 100);
value = (((int) value * 0x3f) / 100) << 4;
value |= i2c_read_reg(HPOUT_CTRL) & ~(0x3f << 4);
i2c_write_reg(HPOUT_CTRL, value);
}
/****************************************************************************************
@@ -345,17 +345,16 @@ static void ac101_start(ac_module_t mode) {
i2c_write_reg(0x50, 0x3bc0);
}
if (mode == AC_MODULE_ADC || mode == AC_MODULE_ADC_DAC || mode == AC_MODULE_LINE) {
//I2S1_SDOUT_CTRL
//i2c_write_reg(PLL_CTRL2, 0x8120);
// I2S1_SDOUT_CTRL
// i2c_write_reg(PLL_CTRL2, 0x8120);
i2c_write_reg(0x04, 0x800c);
i2c_write_reg(0x05, 0x800c);
//res |= i2c_write_reg(0x06, 0x3000);
// res |= i2c_write_reg(0x06, 0x3000);
}
if (mode == AC_MODULE_DAC || mode == AC_MODULE_ADC_DAC || mode == AC_MODULE_LINE) {
headset(true);
speaker(true);
ac101_set_earph_volume(100);
ac101_set_spk_volume(100);
uint16_t value = i2c_read_reg(PLL_CTRL2);
value |= 0x8000;
i2c_write_reg(PLL_CTRL2, value);
}
}
@@ -363,8 +362,9 @@ static void ac101_start(ac_module_t mode) {
*
*/
static void ac101_stop(void) {
speaker(false);
headset(false);
uint16_t value = i2c_read_reg(PLL_CTRL2);
value &= ~0x8000;
i2c_write_reg(PLL_CTRL2, value);
}
/****************************************************************************************

View File

@@ -274,6 +274,8 @@ void output_init_i2s(log_level level, char *device, unsigned output_buf_size, ch
if (jack_mutes_amp && jack_inserted_svc()) adac->speaker(false);
else adac->speaker(true);
adac->headset(jack_inserted_svc());
parse_set_GPIO(set_amp_gpio);
esp_pthread_cfg_t cfg = esp_pthread_get_default_config();

View File

@@ -21,7 +21,7 @@ sub needsClient {
sub validFor {
my ($class, $client) = @_;
return $client->model eq 'squeezeesp32';
return $client->model eq 'squeezeesp32' && $client->displayWidth;
}
sub page {

56
squeezelite.cmake Normal file
View File

@@ -0,0 +1,56 @@
if(NOT SDKCONFIG OR NOT IDF_PATH OR NOT IDF_TARGET )
message(FATAL_ERROR "squeezelite should not be made outside of the main project !")
endif()
function(___register_flash target_name sub_type)
partition_table_get_partition_info(otaapp_offset "--partition-type app --partition-subtype ${sub_type}" "offset")
esptool_py_flash_project_args(${target_name} ${otaapp_offset} ${build_dir}/${target_name}.bin FLASH_IN_PROJECT)
esptool_py_custom_target(${target_name}-flash ${target_name} "${target_name}")
endfunction()
function(___create_new_target target_name)
idf_build_get_property(build_dir BUILD_DIR)
set(target_elf ${target_name}.elf)
# Create a dummy file to work around CMake requirement of having a source
# file while adding an executable
set(target_elf_src ${CMAKE_BINARY_DIR}/${target_name}_src.c)
add_custom_command(OUTPUT ${target_elf_src}
COMMAND ${CMAKE_COMMAND} -E touch ${target_elf_src}
VERBATIM)
add_custom_target(_${target_name}_elf DEPENDS "${target_elf_src}" )
add_executable(${target_elf} "${target_elf_src}")
add_dependencies(${target_elf} _${target_name}_elf)
add_dependencies(${target_elf} "recovery.elf")
set_property(TARGET ${target_elf} PROPERTY RECOVERY_BUILD 0 )
set_property(TARGET ${target_elf} PROPERTY RECOVERY_PREFIX app_${target_name})
idf_build_get_property(bca BUILD_COMPONENT_ALIASES)
target_link_libraries(${target_elf} ${bca})
set(target_name_mapfile "${target_name}.map")
target_link_libraries(${target_elf} "-Wl,--cref -Wl,--Map=${CMAKE_BINARY_DIR}/${target_name_mapfile}")
add_custom_command(
TARGET ${target_elf}
POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo "Generated ${build_dir}/${target_name}.bin"
#COMMAND echo ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${esptool_elf2image_args}
#COMMAND echo ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_ELF2IMAGE_OPTIONS}
COMMAND ${ESPTOOLPY} elf2image ${ESPTOOLPY_FLASH_OPTIONS} ${ESPTOOLPY_ELF2IMAGE_OPTIONS}
-o "${build_dir}/${target_name}.bin" "${target_name}.elf"
DEPENDS "${target_name}.elf"
WORKING_DIRECTORY ${build_dir}
COMMENT "Generating binary image from built executable"
VERBATIM
)
set_property(DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" APPEND PROPERTY
ADDITIONAL_MAKE_CLEAN_FILES
"${build_dir}/${target_name_mapfile}" "${build_dir}/${target_elf_src}" )
endfunction()
___create_new_target(squeezelite )
___register_flash(squeezelite ota_0)