# To build the image for a branch or a tag of IDF, pass --build-arg IDF_CLONE_BRANCH_OR_TAG=name.
# To build the image for a branch or a tag of IDF, pass --build-arg IDF_CLONE_BRANCH_OR_TAG=name.
# To build the image with a specific commit ID of IDF, pass --build-arg IDF_CHECKOUT_REF=commit-id.
# To build the image with a specific commit ID of IDF, pass --build-arg IDF_CHECKOUT_REF=commit-id.
# It is possibe to combine both, e.g.:
# It is possibe to combine both, e.g.:
# IDF_CLONE_BRANCH_OR_TAG=release/vX.Y
# IDF_CLONE_BRANCH_OR_TAG=release/vX.Y
# IDF_CHECKOUT_REF=<some commit on release/vX.Y branch>.
# IDF_CHECKOUT_REF=<some commit on release/vX.Y branch>.
-# The following commit contains the ldgen fix: eab738c79e063b3d6f4c345ea5e1d4f8caef725b
-# to build an image using that commit: docker build . --build-arg IDF_CHECKOUT_REF=eab738c79e063b3d6f4c345ea5e1d4f8caef725b -t sle118/squeezelite-esp32-idfv43
-# Docker build for release 4.3.2 as of 2022/02/28
-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/4001060963585.html) or an external amplifier if you want direct speaker connection. Note that there is a version with AC101 codec and another one with ES8388 with probably two variants - these boards are a mess (see below)
+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://aliexpress.com/item/4000130915903.html) or an external amplifier if you want direct speaker connection. Note that there is a version with AC101 codec and another one with ES8388 with probably two variants - these boards are a mess (see below)
The board shown above has the following IO set
The board shown above has the following IO set
- amplifier: GPIO21
- amplifier: GPIO21
@@ -174,9 +174,9 @@ Default and only "host" is 1 as others are used already by flash and spiram. The
### DAC/I2S
### DAC/I2S
The NVS parameter "dac_config" set the gpio used for i2s communication with your DAC. You can define the defaults at compile time but nvs parameter takes precedence except for SqueezeAMP and A1S where these are forced at runtime. Syntax is
The NVS parameter "dac_config" set the gpio used for i2s communication with your DAC. You can define the defaults at compile time but nvs parameter takes precedence except for SqueezeAMP and A1S where these are forced at runtime. Syntax is
-if "model" is not set or is not recognized, then default "I2S" is used. The option "mck" is used for some codecs that require a master clock (although they should not). Only GPIO0 can be used as MCLK and be aware that this cannot coexit with RMII Ethernet (see ethernet section below). I2C parameters are optional and only needed if your DAC requires an I2C control (See 'dac_controlset' below). Note that "i2c" parameters are decimal, hex notation is not allowed.
+if "model" is not set or is not recognized, then default "I2S" is used. The option "mck" is used for some codecs that require a master clock (although they should not). By default GPIO0 is used as MCLK and only recent builds (none as or 2023/05/15) can use 1 or 2. Also be aware that this cannot coexit with RMII Ethernet (see ethernet section below). I2C parameters are optional and only needed if your DAC requires an I2C control (See 'dac_controlset' below). Note that "i2c" parameters are decimal, hex notation is not allowed.
So far, TAS57xx, TAS5713, AC101, WM8978 and ES8388 are recognized models where the proper init sequence/volume/power controls are sent. For other codecs that might require an I2C commands, please use the parameter "dac_controlset" that allows definition of simple commands to be sent over i2c for init, power, speakder and headset on and off using a JSON syntax:
So far, TAS57xx, TAS5713, AC101, WM8978 and ES8388 are recognized models where the proper init sequence/volume/power controls are sent. For other codecs that might require an I2C commands, please use the parameter "dac_controlset" that allows definition of simple commands to be sent over i2c for init, power, speakder and headset on and off using a JSON syntax:
```json
```json
@@ -305,7 +305,7 @@ See [set_GPIO](#set-gpio) for how to set the green and red LEDs. In addition, th
```
```
[green=0..100][,red=0..100]
[green=0..100][,red=0..100]
```
```
-NB: For well-known configuration, this is ignored
+NB: For well-known configuration, GPIO affected to green and red LED cannot be changed but brightness option applies
### LED Strip
### LED Strip
One LED strip with up to 255 addressable LEDs can be configured to offer enhanced visualizations. The LED strip can also be controlled remotely though the LMS server (using the CLI interface). Currently only WS2812B LEDs are supported. Set the LED Strip configuration (or NVS led_vu_config) to `WS2812,length=<n>,gpio=<gpio>, where <n> is the number of leds in the strip (1..255), and <gpio> is the data pin.`
One LED strip with up to 255 addressable LEDs can be configured to offer enhanced visualizations. The LED strip can also be controlled remotely though the LMS server (using the CLI interface). Currently only WS2812B LEDs are supported. Set the LED Strip configuration (or NVS led_vu_config) to `WS2812,length=<n>,gpio=<gpio>, where <n> is the number of leds in the strip (1..255), and <gpio> is the data pin.`
-// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-/*
-Architecture:
-
-We can initialize a SPI driver, but we don't talk to the SPI driver itself, we address a device. A device essentially
-is a combination of SPI port and CS pin, plus some information about the specifics of communication to the device
-(timing, command/address length etc). The arbitration between tasks is also in conception of devices.
-
-A device can work in interrupt mode and polling mode, and a third but
-complicated mode which combines the two modes above:
-
-1. Work in the ISR with a set of queues; one per device.
-
- The idea is that to send something to a SPI device, you allocate a
- transaction descriptor. It contains some information about the transfer
- like the lenghth, address, command etc, plus pointers to transmit and
- receive buffer. The address of this block gets pushed into the transmit
- queue. The SPI driver does its magic, and sends and retrieves the data
- eventually. The data gets written to the receive buffers, if needed the
- transaction descriptor is modified to indicate returned parameters and
- the entire thing goes into the return queue, where whatever software
- initiated the transaction can retrieve it.
-
- The entire thing is run from the SPI interrupt handler. If SPI is done
- transmitting/receiving but nothing is in the queue, it will not clear the
- SPI interrupt but just disable it by esp_intr_disable. This way, when a
- new thing is sent, pushing the packet into the send queue and re-enabling
- the interrupt (by esp_intr_enable) will trigger the interrupt again, which
- can then take care of the sending.
-
-2. Work in the polling mode in the task.
-
- In this mode we get rid of the ISR, FreeRTOS queue and task switching, the
- task is no longer blocked during a transaction. This increase the cpu
- load, but decrease the interval of SPI transactions. Each time only one
- device (in one task) can send polling transactions, transactions to
- other devices are blocked until the polling transaction of current device
- is done.
-
- In the polling mode, the queue is not used, all the operations are done
- in the task. The task calls ``spi_device_polling_start`` to setup and start
- a new transaction, then call ``spi_device_polling_end`` to handle the
- return value of the transaction.
-
- To handle the arbitration among devices, the device "temporarily" acquire
- a bus by the ``device_acquire_bus_internal`` function, which writes
- dev_request by CAS operation. Other devices which wants to send polling
- transactions but don't own the bus will block and wait until given the
- semaphore which indicates the ownership of bus.
-
- In case of the ISR is still sending transactions to other devices, the ISR
- should maintain an ``random_idle`` flag indicating that it's not doing
- transactions. When the bus is locked, the ISR can only send new
- transactions to the acquiring device. The ISR will automatically disable
- itself and send semaphore to the device if the ISR is free. If the device
- sees the random_idle flag, it can directly start its polling transaction.
- Otherwise it should block and wait for the semaphore from the ISR.
-
- After the polling transaction, the driver will release the bus. During the
- release of the bus, the driver search all other devices to see whether
- there is any device waiting to acquire the bus, if so, acquire for it and
- send it a semaphore if the device queue is empty, or invoke the ISR for
- it. If all other devices don't need to acquire the bus, but there are
- still transactions in the queues, the ISR will also be invoked.
-
- To get better polling efficiency, user can call ``spi_device_acquire_bus``
- function, which also calls the ``spi_bus_lock_acquire_core`` function,
- before a series of polling transactions to a device. The bus acquiring and
- task switching before and after the polling transaction will be escaped.
-
-3. Mixed mode
-
- The driver is written under the assumption that polling and interrupt
- transactions are not happening simultaneously. When sending polling
- transactions, it will check whether the ISR is active, which includes the
- case the ISR is sending the interrupt transactions of the acquiring
- device. If the ISR is still working, the routine sending a polling
- transaction will get blocked and wait until the semaphore from the ISR
- which indicates the ISR is free now.
-
- A fatal case is, a polling transaction is in flight, but the ISR received
- an interrupt transaction. The behavior of the driver is unpredictable,
- which should be strictly forbidden.
-
-We have two bits to control the interrupt:
-
-1. The slave->trans_done bit, which is automatically asserted when a transaction is done.
-
- This bit is cleared during an interrupt transaction, so that the interrupt
- will be triggered when the transaction is done, or the SW can check the
- bit to see if the transaction is done for polling transactions.
-
- When no transaction is in-flight, the bit is kept active, so that the SW
- can easily invoke the ISR by enable the interrupt.
-
-2. The system interrupt enable/disable, controlled by esp_intr_enable and esp_intr_disable.
-
- The interrupt is disabled (by the ISR itself) when no interrupt transaction
- is queued. When the bus is not occupied, any task, which queues a
- transaction into the queue, will enable the interrupt to invoke the ISR.
- When the bus is occupied by a device, other device will put off the
- invoking of ISR to the moment when the bus is released. The device
- acquiring the bus can still send interrupt transactions by enable the
- interrupt.
-
-*/
-
-#include <string.h>
-#include "driver/spi_common_internal.h"
-#include "driver/spi_master.h"
-
-#include "esp_log.h"
-#include "freertos/task.h"
-#include "freertos/queue.h"
-#include "freertos/semphr.h"
-#include "soc/soc_memory_layout.h"
-#include "driver/gpio.h"
-#include "hal/spi_hal.h"
-#include "esp_heap_caps.h"
-
-
-typedef struct spi_device_t spi_device_t;
-
-/// struct to hold private transaction data (like tx and rx buffer for DMA).
-typedef struct {
- spi_transaction_t *trans;
- const uint32_t *buffer_to_send; //equals to tx_data, if SPI_TRANS_USE_RXDATA is applied; otherwise if original buffer wasn't in DMA-capable memory, this gets the address of a temporary buffer that is;
- //otherwise sets to the original buffer or NULL if no buffer is assigned.
- uint32_t *buffer_to_rcv; // similar to buffer_to_send
-} spi_trans_priv_t;
-
-typedef struct {
- int id;
- spi_device_t* device[DEV_NUM_MAX];
- intr_handle_t intr;
- spi_hal_context_t hal;
- spi_trans_priv_t cur_trans_buf;
- int cur_cs; //current device doing transaction
- const spi_bus_attr_t* bus_attr;
-
- /**
- * the bus is permanently controlled by a device until `spi_bus_release_bus`` is called. Otherwise
- * the acquiring of SPI bus will be freed when `spi_device_polling_end` is called.
- */
- spi_device_t* device_acquiring_lock;
-
-//debug information
- bool polling; //in process of a polling, avoid of queue new transactions into ISR
- (dev_config->flags & SPI_DEVICE_HALFDUPLEX), "In full-duplex mode, only support cs pretrans delay = 1 and without address_bits and command_bits", ESP_ERR_INVALID_ARG);
- // This function may assign a new acquiring device, otherwise it will suggest a desired device with BG active
- // We use either of them without further searching in the devices.
- // If the return value is true, it means either there's no acquiring device, or the acquiring device's BG is active,
- // We stay in the ISR to deal with those transactions of desired device, otherwise nothing will be done, check whether we need to resume some other tasks, or just quit the ISR
- SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_RXDATA)==0 || trans_desc->rxlength <= 32, "SPI_TRANS_USE_RXDATA only available for rxdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
- SPI_CHECK((trans_desc->flags & SPI_TRANS_USE_TXDATA)==0 || trans_desc->length <= 32, "SPI_TRANS_USE_TXDATA only available for txdata transfer <= 32 bits", ESP_ERR_INVALID_ARG);
- SPI_CHECK(trans_desc->length <= bus_attr->max_transfer_sz*8, "txdata transfer > host maximum", ESP_ERR_INVALID_ARG);
- SPI_CHECK(trans_desc->rxlength <= bus_attr->max_transfer_sz*8, "rxdata transfer > host maximum", ESP_ERR_INVALID_ARG);
- SPI_CHECK(is_half_duplex || trans_desc->rxlength <= trans_desc->length, "rx length > tx length in full duplex mode", ESP_ERR_INVALID_ARG);
- SPI_CHECK(!is_half_duplex || !bus_attr->dma_enabled || !rx_enabled || !tx_enabled, "SPI half duplex mode does not support using DMA with both MOSI and MISO phases.", ESP_ERR_INVALID_ARG );
-#elif CONFIG_IDF_TARGET_ESP32S3
- SPI_CHECK(!is_half_duplex || !tx_enabled || !rx_enabled, "SPI half duplex mode is not supported when both MOSI and MISO phases are enabled.", ESP_ERR_INVALID_ARG);
-#endif
- //MOSI phase is skipped only when both tx_buffer and SPI_TRANS_USE_TXDATA are not set.
- SPI_CHECK(trans_desc->length != 0 || !tx_enabled, "trans tx_buffer should be NULL and SPI_TRANS_USE_TXDATA should be cleared to skip MOSI phase.", ESP_ERR_INVALID_ARG);
- //MISO phase is skipped only when both rx_buffer and SPI_TRANS_USE_RXDATA are not set.
- //If set rxlength=0 in full_duplex mode, it will be automatically set to length
- SPI_CHECK(!is_half_duplex || trans_desc->rxlength != 0 || !rx_enabled, "trans rx_buffer should be NULL and SPI_TRANS_USE_RXDATA should be cleared to skip MISO phase.", ESP_ERR_INVALID_ARG);
- //In Full duplex mode, default rxlength to be the same as length, if not filled in.
- // set rxlength to length is ok, even when rx buffer=NULL
- if (trans_desc->rxlength==0 && !is_half_duplex) {
- trans_desc->rxlength=trans_desc->length;
- }
- //Dummy phase is not available when both data out and in are enabled, regardless of FD or HD mode.
- SPI_CHECK(!tx_enabled || !rx_enabled || !dummy_enabled || !extra_dummy_enabled, "Dummy phase is not available when both data out and in are enabled", ESP_ERR_INVALID_ARG);
- esp_err_t ret = check_trans_valid(handle, trans_desc);
- if (ret != ESP_OK) return ret;
-
- spi_host_t *host = handle->host;
-
- SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot queue new transaction while previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE );
-
- spi_trans_priv_t trans_buf;
- ret = setup_priv_desc(trans_desc, &trans_buf, (host->bus_attr->dma_enabled));
- if (ret != ESP_OK) return ret;
-
-#ifdef CONFIG_PM_ENABLE
- esp_pm_lock_acquire(host->bus_attr->pm_lock);
-#endif
- //Send to queue and invoke the ISR.
-
- BaseType_t r = xQueueSend(handle->trans_queue, (void *)&trans_buf, ticks_to_wait);
- if (!r) {
- ret = ESP_ERR_TIMEOUT;
-#ifdef CONFIG_PM_ENABLE
- //Release APB frequency lock
- esp_pm_lock_release(host->bus_attr->pm_lock);
-#endif
- goto clean_up;
- }
-
- // The ISR will be invoked at correct time by the lock with `spi_bus_intr_enable`.
- ret = spi_bus_lock_bg_request(handle->dev_lock);
- SPI_CHECK(ticks_to_wait == portMAX_DELAY, "currently timeout is not available for polling transactions", ESP_ERR_INVALID_ARG);
- ret = check_trans_valid(handle, trans_desc);
- if (ret!=ESP_OK) return ret;
- SPI_CHECK(!spi_bus_device_is_polling(handle), "Cannot send polling transaction while the previous polling transaction is not terminated.", ESP_ERR_INVALID_STATE );
-
- /* If device_acquiring_lock is set to handle, it means that the user has already
- * acquired the bus thanks to the function `spi_device_acquire_bus()`.
- * In that case, we don't need to take the lock again. */
- spi_host_t *host = handle->host;
- if (host->device_acquiring_lock != handle) {
- ret = spi_bus_lock_acquire_start(handle->dev_lock, ticks_to_wait);
- } else {
- ret = spi_bus_lock_wait_bg_done(handle->dev_lock, ticks_to_wait);
- }
- if (ret != ESP_OK) return ret;
-
- ret = setup_priv_desc(trans_desc, &host->cur_trans_buf, (host->bus_attr->dma_enabled));
+ ESP_LOGE(TAG,"Connection state event received while status was unconnected. Routing message to connecting state handler. State : %u",param->conn_stat.state);
+ if (param->conn_stat.state == ESP_A2D_CONNECTION_STATE_CONNECTED){
- uint32_t caps[SOC_MEMORY_TYPE_NO_PRIOS]; ///< Capabilities for the type of memory in this heap (as a prioritised set). Copied from soc_memory_types so it's in RAM not flash.
- intptr_t start;
- intptr_t end;
- multi_heap_lock_t heap_mux;
- multi_heap_handle_t heap;
- SLIST_ENTRY(heap_t_) next;
-} heap_t;
-
-/* All registered heaps.
-
- Forms a single linked list, even though most entries are contiguous.
- This means at the expense of 4 bytes per heap, new heaps can be
- * This function initialises a heap at the specified address, and returns a handle for future heap operations.
- *
- * There is no equivalent function for deregistering a heap - if all blocks in the heap are free, you can immediately start using the memory for other purposes.
- *
- * @param start Start address of the memory to use for a new heap.
- * @param size Size (in bytes) of the new heap.
- *
- * @return Handle of a new heap ready for use, or NULL if the heap region was too small to be initialised.