Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 047c7c87d7 | |||
| 94b5cdbfc4 | |||
| 5c535490ea |
@@ -54,6 +54,8 @@ if (DEFINED ENV{ESP_IDF_VERSION})
|
|||||||
|
|
||||||
set(EXCLUDE_COMPONENTS "Simulator")
|
set(EXCLUDE_COMPONENTS "Simulator")
|
||||||
|
|
||||||
|
idf_build_set_property(LINK_OPTIONS "-Wl,--allow-multiple-definition" APPEND)
|
||||||
|
|
||||||
# Panic handler wrapping is only available on Xtensa architecture
|
# Panic handler wrapping is only available on Xtensa architecture
|
||||||
if (CONFIG_IDF_TARGET_ARCH_XTENSA)
|
if (CONFIG_IDF_TARGET_ARCH_XTENSA)
|
||||||
idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=esp_panic_handler" APPEND)
|
idf_build_set_property(LINK_OPTIONS "-Wl,--wrap=esp_panic_handler" APPEND)
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
||||||
|
|
||||||
|
idf_component_register(
|
||||||
|
SRCS ${SOURCE_FILES}
|
||||||
|
INCLUDE_DIRS "Source"
|
||||||
|
REQUIRES Tactility esp_lvgl_port ILI934x FT6x36 PwmBacklight driver vfs fatfs
|
||||||
|
)
|
||||||
@@ -0,0 +1,105 @@
|
|||||||
|
#include "PwmBacklight.h"
|
||||||
|
#include "devices/Display.h"
|
||||||
|
#include <driver/gpio.h>
|
||||||
|
|
||||||
|
#include <tactility/device.h>
|
||||||
|
#include <tactility/drivers/i2c_controller.h>
|
||||||
|
#include <tactility/log.h>
|
||||||
|
#include <tactility/error.h>
|
||||||
|
#include <tactility/freertos/freertos.h>
|
||||||
|
|
||||||
|
#include <Tactility/hal/Configuration.h>
|
||||||
|
|
||||||
|
using namespace tt::hal;
|
||||||
|
|
||||||
|
static constexpr auto* TAG = "ES3C28P";
|
||||||
|
static constexpr uint8_t ES8311_I2C_ADDR = 0x18;
|
||||||
|
|
||||||
|
static error_t initSound(::Device* i2c_controller) {
|
||||||
|
static constexpr uint8_t ENABLED_BULK_DATA[] = {
|
||||||
|
0x00, 0x80, // RESET/CSM POWER ON
|
||||||
|
0x01, 0x3F, // CLOCK_MANAGER/ use MCLK pin (external), all clocks on
|
||||||
|
0x02, 0x00, // CLOCK_MANAGER/ pre_div=1 pre_multi=1 (256x MCLK is correct ratio)
|
||||||
|
0x0D, 0x01, // SYSTEM/ Power up analog circuitry
|
||||||
|
0x12, 0x00, // SYSTEM/ power-up DAC
|
||||||
|
0x13, 0x10, // SYSTEM/ Enable output to HP drive
|
||||||
|
0x32, 0xBF, // DAC/ DAC volume (0xBF == ±0 dB)
|
||||||
|
0x37, 0x08, // DAC/ Bypass DAC equalizer
|
||||||
|
};
|
||||||
|
|
||||||
|
return i2c_controller_write_register_array(
|
||||||
|
i2c_controller,
|
||||||
|
ES8311_I2C_ADDR,
|
||||||
|
ENABLED_BULK_DATA,
|
||||||
|
sizeof(ENABLED_BULK_DATA),
|
||||||
|
pdMS_TO_TICKS(1000)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static error_t initMicrophone(::Device* i2c_controller) {
|
||||||
|
static constexpr uint8_t ENABLED_BULK_DATA[] = {
|
||||||
|
0x00, 0x80, // RESET/CSM POWER ON
|
||||||
|
0x01, 0x3F, // CLOCK_MANAGER/ use MCLK pin (external), all clocks on
|
||||||
|
0x02, 0x00, // CLOCK_MANAGER/ pre_div=1 pre_multi=1
|
||||||
|
0x0D, 0x01, // SYSTEM/ Power up analog circuitry
|
||||||
|
0x0E, 0x02, // SYSTEM/ Enable analog PGA, enable ADC modulator
|
||||||
|
0x14, 0x10, // ADC_REG14: select Mic1p-Mic1n / PGA GAIN (minimum)
|
||||||
|
0x17, 0xFF, // ADC_REG17: ADC_VOLUME (MAXGAIN)
|
||||||
|
0x1C, 0x6A, // ADC_REG1C: ADC Equalizer bypass, cancel DC offset
|
||||||
|
};
|
||||||
|
|
||||||
|
return i2c_controller_write_register_array(
|
||||||
|
i2c_controller,
|
||||||
|
ES8311_I2C_ADDR,
|
||||||
|
ENABLED_BULK_DATA,
|
||||||
|
sizeof(ENABLED_BULK_DATA),
|
||||||
|
pdMS_TO_TICKS(1000)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool initBoot() {
|
||||||
|
// 1. Initialize display backlight
|
||||||
|
if (!driver::pwmbacklight::init(LCD_PIN_BACKLIGHT)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Initialize and power on the FM8002E Audio Amplifier (GPIO 1, Active LOW)
|
||||||
|
gpio_config_t io_conf = {};
|
||||||
|
io_conf.intr_type = GPIO_INTR_DISABLE;
|
||||||
|
io_conf.mode = GPIO_MODE_OUTPUT;
|
||||||
|
io_conf.pin_bit_mask = (1ULL << GPIO_NUM_1);
|
||||||
|
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
|
||||||
|
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
|
||||||
|
gpio_config(&io_conf);
|
||||||
|
|
||||||
|
// Drive LOW to enable the speaker amplifier
|
||||||
|
gpio_set_level(GPIO_NUM_1, 0);
|
||||||
|
|
||||||
|
// 3. Configure the ES8311 Codec over the I2C bus
|
||||||
|
auto* i2c_bus = device_find_by_name("i2c0");
|
||||||
|
if (i2c_bus != nullptr) {
|
||||||
|
error_t error = initSound(i2c_bus);
|
||||||
|
if (error != ERROR_NONE) {
|
||||||
|
LOG_E(TAG, "Failed to enable ES8311 speaker: %s", error_to_string(error));
|
||||||
|
}
|
||||||
|
error = initMicrophone(i2c_bus);
|
||||||
|
if (error != ERROR_NONE) {
|
||||||
|
LOG_E(TAG, "Failed to enable ES8311 microphone: %s", error_to_string(error));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
LOG_E(TAG, "i2c0 bus not found, skipping ES8311 initialization");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DeviceVector createDevices() {
|
||||||
|
return {
|
||||||
|
createDisplay()
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
extern const Configuration hardwareConfiguration = {
|
||||||
|
.initBoot = initBoot,
|
||||||
|
.createDevices = createDevices
|
||||||
|
};
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
#include "Display.h"
|
||||||
|
|
||||||
|
#include <Ft6x36Touch.h>
|
||||||
|
#include <Ili934xDisplay.h>
|
||||||
|
#include <PwmBacklight.h>
|
||||||
|
|
||||||
|
static std::shared_ptr<tt::hal::touch::TouchDevice> createTouch() {
|
||||||
|
auto configuration = std::make_unique<Ft6x36Touch::Configuration>(
|
||||||
|
I2C_NUM_0,
|
||||||
|
240, // xMax (native portrait width)
|
||||||
|
320, // yMax (native portrait height)
|
||||||
|
true, // swapXy
|
||||||
|
true, // mirrorX
|
||||||
|
false, // mirrorY
|
||||||
|
GPIO_NUM_18, // Touch Reset (RST)
|
||||||
|
GPIO_NUM_17 // Touch Interrupt (INT)
|
||||||
|
);
|
||||||
|
|
||||||
|
return std::make_shared<Ft6x36Touch>(std::move(configuration));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay() {
|
||||||
|
Ili934xDisplay::Configuration panel_configuration = {
|
||||||
|
.horizontalResolution = LCD_HORIZONTAL_RESOLUTION,
|
||||||
|
.verticalResolution = LCD_VERTICAL_RESOLUTION,
|
||||||
|
.gapX = 0,
|
||||||
|
.gapY = 0,
|
||||||
|
.swapXY = true,
|
||||||
|
.mirrorX = false,
|
||||||
|
.mirrorY = false,
|
||||||
|
.invertColor = false,
|
||||||
|
.swapBytes = true,
|
||||||
|
.bufferSize = LCD_BUFFER_SIZE,
|
||||||
|
.touch = createTouch(),
|
||||||
|
.backlightDutyFunction = driver::pwmbacklight::setBacklightDuty,
|
||||||
|
.resetPin = GPIO_NUM_NC,
|
||||||
|
.rgbElementOrder = LCD_RGB_ELEMENT_ORDER_BGR
|
||||||
|
};
|
||||||
|
|
||||||
|
auto spi_configuration = std::make_shared<Ili934xDisplay::SpiConfiguration>(Ili934xDisplay::SpiConfiguration {
|
||||||
|
.spiHostDevice = LCD_SPI_HOST,
|
||||||
|
.csPin = LCD_PIN_CS,
|
||||||
|
.dcPin = LCD_PIN_DC,
|
||||||
|
.pixelClockFrequency = 40'000'000,
|
||||||
|
.transactionQueueDepth = 10
|
||||||
|
});
|
||||||
|
|
||||||
|
return std::make_shared<Ili934xDisplay>(panel_configuration, spi_configuration, true);
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <Tactility/hal/display/DisplayDevice.h>
|
||||||
|
#include <driver/gpio.h>
|
||||||
|
#include <driver/spi_common.h>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
// Display
|
||||||
|
constexpr auto LCD_SPI_HOST = SPI2_HOST;
|
||||||
|
constexpr auto LCD_PIN_CS = GPIO_NUM_10;
|
||||||
|
constexpr auto LCD_PIN_DC = GPIO_NUM_46;
|
||||||
|
constexpr auto LCD_HORIZONTAL_RESOLUTION = 320;
|
||||||
|
constexpr auto LCD_VERTICAL_RESOLUTION = 240;
|
||||||
|
constexpr auto LCD_BUFFER_HEIGHT = LCD_VERTICAL_RESOLUTION / 10;
|
||||||
|
constexpr auto LCD_BUFFER_SIZE = LCD_HORIZONTAL_RESOLUTION * LCD_BUFFER_HEIGHT;
|
||||||
|
|
||||||
|
// Backlight pin
|
||||||
|
constexpr auto LCD_PIN_BACKLIGHT = GPIO_NUM_45;
|
||||||
|
|
||||||
|
std::shared_ptr<tt::hal::display::DisplayDevice> createDisplay();
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
#include <tactility/module.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
static error_t start() {
|
||||||
|
// Empty for now
|
||||||
|
return ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static error_t stop() {
|
||||||
|
// Empty for now
|
||||||
|
return ERROR_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Module es3c28p_module = {
|
||||||
|
.name = "es3c28p",
|
||||||
|
.start = start,
|
||||||
|
.stop = stop,
|
||||||
|
.symbols = nullptr,
|
||||||
|
.internal = nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
[general]
|
||||||
|
vendor=LCDWIKI
|
||||||
|
name=ES3C28P
|
||||||
|
|
||||||
|
[apps]
|
||||||
|
launcherAppId=Launcher
|
||||||
|
|
||||||
|
[hardware]
|
||||||
|
target=ESP32S3
|
||||||
|
flashSize=16MB
|
||||||
|
spiRam=true
|
||||||
|
spiRamMode=OCT
|
||||||
|
spiRamSpeed=120M
|
||||||
|
tinyUsb=true
|
||||||
|
esptoolFlashFreq=120M
|
||||||
|
bluetooth=true
|
||||||
|
|
||||||
|
[display]
|
||||||
|
size=2.8"
|
||||||
|
shape=rectangle
|
||||||
|
dpi=143
|
||||||
|
|
||||||
|
[lvgl]
|
||||||
|
colorDepth=16
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
dependencies:
|
||||||
|
- Platforms/platform-esp32
|
||||||
|
dts: es3c28p.dts
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/dts-v1/;
|
||||||
|
|
||||||
|
#include <tactility/bindings/root.h>
|
||||||
|
#include <tactility/bindings/esp32_ble.h>
|
||||||
|
#include <tactility/bindings/esp32_gpio.h>
|
||||||
|
#include <tactility/bindings/esp32_i2c.h>
|
||||||
|
#include <tactility/bindings/esp32_sdmmc.h>
|
||||||
|
#include <tactility/bindings/esp32_spi.h>
|
||||||
|
#include <tactility/bindings/esp32_i2s.h>
|
||||||
|
|
||||||
|
/ {
|
||||||
|
compatible = "root";
|
||||||
|
model = "LCDWIKI ES3C28P";
|
||||||
|
|
||||||
|
ble0 {
|
||||||
|
compatible = "espressif,esp32-ble";
|
||||||
|
};
|
||||||
|
|
||||||
|
gpio0 {
|
||||||
|
compatible = "espressif,esp32-gpio";
|
||||||
|
gpio-count = <49>;
|
||||||
|
};
|
||||||
|
|
||||||
|
i2c0 {
|
||||||
|
compatible = "espressif,esp32-i2c";
|
||||||
|
port = <I2C_NUM_0>;
|
||||||
|
clock-frequency = <400000>;
|
||||||
|
pin-sda = <&gpio0 16 GPIO_FLAG_NONE>;
|
||||||
|
pin-scl = <&gpio0 15 GPIO_FLAG_NONE>;
|
||||||
|
};
|
||||||
|
|
||||||
|
i2s0 {
|
||||||
|
compatible = "espressif,esp32-i2s";
|
||||||
|
port = <I2S_NUM_0>;
|
||||||
|
pin-bclk = <&gpio0 5 GPIO_FLAG_NONE>;
|
||||||
|
pin-ws = <&gpio0 7 GPIO_FLAG_NONE>;
|
||||||
|
pin-data-out = <&gpio0 6 GPIO_FLAG_NONE>;
|
||||||
|
pin-data-in = <&gpio0 8 GPIO_FLAG_NONE>;
|
||||||
|
pin-mclk = <&gpio0 4 GPIO_FLAG_NONE>;
|
||||||
|
};
|
||||||
|
|
||||||
|
display_spi: spi0 {
|
||||||
|
compatible = "espressif,esp32-spi";
|
||||||
|
host = <SPI2_HOST>;
|
||||||
|
pin-mosi = <&gpio0 11 GPIO_FLAG_NONE>;
|
||||||
|
pin-sclk = <&gpio0 12 GPIO_FLAG_NONE>;
|
||||||
|
};
|
||||||
|
|
||||||
|
sdmmc0 {
|
||||||
|
compatible = "espressif,esp32-sdmmc";
|
||||||
|
pin-clk = <&gpio0 38 GPIO_FLAG_NONE>;
|
||||||
|
pin-cmd = <&gpio0 40 GPIO_FLAG_NONE>;
|
||||||
|
pin-d0 = <&gpio0 39 GPIO_FLAG_NONE>;
|
||||||
|
pin-d1 = <&gpio0 41 GPIO_FLAG_NONE>;
|
||||||
|
pin-d2 = <&gpio0 48 GPIO_FLAG_NONE>;
|
||||||
|
pin-d3 = <&gpio0 47 GPIO_FLAG_NONE>;
|
||||||
|
bus-width = <4>;
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -3,5 +3,5 @@ file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
|||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
INCLUDE_DIRS "Source"
|
INCLUDE_DIRS "Source"
|
||||||
REQUIRES Tactility esp_lvgl_port esp_lcd EspLcdCompat esp_lcd_ili9881c esp_lcd_st7123 esp_lcd_touch_st7123 GT911 PwmBacklight driver esp_driver_i2c vfs fatfs ina226-module
|
REQUIRES Tactility esp_lvgl_port esp_lcd EspLcdCompat esp_lcd_ili9881c esp_lcd_st7123 esp_lcd_touch_st7123 GT911 PwmBacklight driver vfs fatfs ina226-module
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
# GameBoy side-loaded ELF support notes
|
||||||
|
|
||||||
|
This branch records the firmware-side changes used to make the Tactility GameBoy emulator prototype load past the generic `missing symbol` failure on an ESP32-S3 ES3C28P board.
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
|
||||||
|
Side-loaded `.app` packages are relocated by the firmware ELF loader. The app can build successfully against the local SDK but still fail at runtime if the board firmware does not export every dynamic symbol used by the app.
|
||||||
|
|
||||||
|
For the GameBoy prototype, USB serial logs showed the emulator app was being found and started, but firmware without the needed LVGL exports showed missing-symbol failures for the canvas path.
|
||||||
|
|
||||||
|
## Firmware changes in this branch
|
||||||
|
|
||||||
|
`TactilityC/Source/tt_init.cpp` now includes LVGL and exports the core LVGL canvas/display functions the GameBoy app needs:
|
||||||
|
|
||||||
|
- `lv_canvas_create`
|
||||||
|
- `lv_canvas_set_buffer`
|
||||||
|
- `lv_obj_invalidate`
|
||||||
|
- `lv_display_get_horizontal_resolution`
|
||||||
|
- `lv_display_get_vertical_resolution`
|
||||||
|
|
||||||
|
These are exported through the existing `main_symbols[]` table with `ESP_ELFSYM_EXPORT(...)`, making them visible to side-loaded ESP32-S3 app ELFs.
|
||||||
|
|
||||||
|
The branch also removes the `AlwaysRun` devicetree delete target from `Firmware/CMakeLists.txt`. During iterative firmware builds this target deleted `Generated/devicetree.c` while compile rules still depended on it, causing intermittent build failures. The devicetree generation rule now depends directly on the source YAML.
|
||||||
|
|
||||||
|
## Verification performed
|
||||||
|
|
||||||
|
On the iMac build host:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd ~/Projects/gitea/tactility
|
||||||
|
. ~/esp/esp-idf/export.sh
|
||||||
|
python3 device.py es3c28p
|
||||||
|
idf.py build
|
||||||
|
idf.py -p /dev/ttyACM0 flash
|
||||||
|
```
|
||||||
|
|
||||||
|
Build result:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Tactility.bin binary size 0x2b82b0 bytes
|
||||||
|
Smallest app partition is 0x400000 bytes
|
||||||
|
0x147d50 bytes (32%) free
|
||||||
|
```
|
||||||
|
|
||||||
|
Flash target:
|
||||||
|
|
||||||
|
```text
|
||||||
|
ESP32-S3 ES3C28P
|
||||||
|
USB serial: /dev/ttyACM0
|
||||||
|
MAC: 14:c1:9f:d0:5c:5c
|
||||||
|
```
|
||||||
|
|
||||||
|
Runtime serial showed the GameBoy core loop running and reporting approximately 49-50 FPS:
|
||||||
|
|
||||||
|
```text
|
||||||
|
GAMEBOY_FPS 50
|
||||||
|
GAMEBOY_FPS 49
|
||||||
|
GAMEBOY_FPS 49
|
||||||
|
```
|
||||||
|
|
||||||
|
## Current caveat
|
||||||
|
|
||||||
|
The app loop/FPS is running, but the photographed device showed the GameBoy framebuffer was not visibly rendering yet. That remaining issue is in the app/UI canvas presentation path, not the firmware missing-symbol issue addressed by this branch.
|
||||||
|
|
||||||
|
## Related app work
|
||||||
|
|
||||||
|
The app-side prototype lives in the separate Gitea repo:
|
||||||
|
|
||||||
|
```text
|
||||||
|
https://git.reynafamily.com/adolforeyna/tactility_apps.git
|
||||||
|
```
|
||||||
|
|
||||||
|
The app branch changes include restoring the LVGL canvas path, using `/data/roms/gb/default.gb` for the flashed data-image test, and printing `GAMEBOY_FPS` markers over USB serial.
|
||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <esp_lcd_types.h>
|
#include <esp_lcd_types.h>
|
||||||
#include <esp_lvgl_port_disp.h>
|
#include <esp_lvgl_port_disp.h>
|
||||||
|
#include <hal/gpio_types.h>
|
||||||
|
|
||||||
constexpr auto DEFAULT_BUFFER_SIZE = 0;
|
constexpr auto DEFAULT_BUFFER_SIZE = 0;
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,6 @@ bool EspLcdSpiDisplay::createIoHandle(esp_lcd_panel_io_handle_t& outHandle) {
|
|||||||
.user_ctx = nullptr,
|
.user_ctx = nullptr,
|
||||||
.lcd_cmd_bits = 8,
|
.lcd_cmd_bits = 8,
|
||||||
.lcd_param_bits = 8,
|
.lcd_param_bits = 8,
|
||||||
.cs_ena_pretrans = 0,
|
|
||||||
.cs_ena_posttrans = 0,
|
|
||||||
.flags = {
|
.flags = {
|
||||||
.dc_high_on_cmd = 0,
|
.dc_high_on_cmd = 0,
|
||||||
.dc_low_on_data = 0,
|
.dc_low_on_data = 0,
|
||||||
|
|||||||
@@ -48,6 +48,11 @@ bool EspLcdTouch::startLvgl(lv_disp_t* display) {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (touchHandle == nullptr) {
|
||||||
|
LOGGER.error("Cannot start LVGL touch: touchHandle is null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (touchDriver != nullptr && touchDriver.use_count() > 1) {
|
if (touchDriver != nullptr && touchDriver.use_count() > 1) {
|
||||||
LOGGER.warn("TouchDriver is still in use.");
|
LOGGER.warn("TouchDriver is still in use.");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ bool init(gpio_num_t pin, uint32_t frequencyHz, ledc_timer_t timer, ledc_channel
|
|||||||
.timer_sel = backlightTimer,
|
.timer_sel = backlightTimer,
|
||||||
.duty = 0,
|
.duty = 0,
|
||||||
.hpoint = 0,
|
.hpoint = 0,
|
||||||
.sleep_mode = LEDC_SLEEP_MODE_NO_ALIVE_NO_PD,
|
|
||||||
.flags = {
|
.flags = {
|
||||||
.output_invert = 0
|
.output_invert = 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -100,17 +100,13 @@ endif ()
|
|||||||
#
|
#
|
||||||
# Devicetree code generation
|
# Devicetree code generation
|
||||||
#
|
#
|
||||||
|
|
||||||
add_custom_target(AlwaysRun
|
|
||||||
COMMAND ${CMAKE_COMMAND} -E rm -f "${GENERATED_DIR}/devicetree.c"
|
|
||||||
)
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT "${GENERATED_DIR}/devicetree.c"
|
OUTPUT "${GENERATED_DIR}/devicetree.c"
|
||||||
"${GENERATED_DIR}/devicetree.h"
|
"${GENERATED_DIR}/devicetree.h"
|
||||||
COMMAND python "${CMAKE_SOURCE_DIR}/Buildscripts/DevicetreeCompiler/compile.py"
|
COMMAND python "${CMAKE_SOURCE_DIR}/Buildscripts/DevicetreeCompiler/compile.py"
|
||||||
"${DEVICETREE_LOCATION}" "${GENERATED_DIR}"
|
"${DEVICETREE_LOCATION}" "${GENERATED_DIR}"
|
||||||
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}"
|
||||||
DEPENDS AlwaysRun "${DEVICETREE_LOCATION}/devicetree.yaml" # AlwaysRun ensures it always gets built
|
DEPENDS "${DEVICETREE_LOCATION}/devicetree.yaml"
|
||||||
COMMENT "Generating devicetree source files..."
|
COMMENT "Generating devicetree source files..."
|
||||||
)
|
)
|
||||||
add_custom_target(Generated DEPENDS "${GENERATED_DIR}/devicetree.c")
|
add_custom_target(Generated DEPENDS "${GENERATED_DIR}/devicetree.c")
|
||||||
|
|||||||
@@ -29,7 +29,6 @@ dependencies:
|
|||||||
espressif/esp_lcd_touch_ft5x06: "1.0.6~1"
|
espressif/esp_lcd_touch_ft5x06: "1.0.6~1"
|
||||||
espressif/esp_io_expander: "1.0.1"
|
espressif/esp_io_expander: "1.0.1"
|
||||||
espressif/esp_io_expander_tca95xx_16bit: "1.0.1"
|
espressif/esp_io_expander_tca95xx_16bit: "1.0.1"
|
||||||
espressif/esp_lcd_axs15231b: "2.0.2"
|
|
||||||
lambage/esp_lcd_touch_ft6336u: "1.0.8"
|
lambage/esp_lcd_touch_ft6336u: "1.0.8"
|
||||||
espressif/esp_lcd_st7701:
|
espressif/esp_lcd_st7701:
|
||||||
version: "1.1.3"
|
version: "1.1.3"
|
||||||
@@ -81,5 +80,5 @@ dependencies:
|
|||||||
version: "1.1.4"
|
version: "1.1.4"
|
||||||
rules:
|
rules:
|
||||||
- if: "target in [esp32s3, esp32p4]"
|
- if: "target in [esp32s3, esp32p4]"
|
||||||
idf: '5.5.2'
|
idf: '>=5.2.0'
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ idf_component_register(
|
|||||||
SRCS ${SOURCES}
|
SRCS ${SOURCES}
|
||||||
INCLUDE_DIRS "include/"
|
INCLUDE_DIRS "include/"
|
||||||
PRIV_INCLUDE_DIRS "private/"
|
PRIV_INCLUDE_DIRS "private/"
|
||||||
REQUIRES TactilityKernel driver esp_driver_i2c vfs fatfs
|
REQUIRES TactilityKernel driver vfs fatfs
|
||||||
)
|
)
|
||||||
|
|
||||||
idf_component_optional_requires(PRIVATE bt usb espressif__usb_host_hid espressif__usb_host_msc)
|
idf_component_optional_requires(PRIVATE bt usb espressif__usb_host_hid espressif__usb_host_msc)
|
||||||
|
|||||||
@@ -167,4 +167,11 @@ bool ble_hci_gate_wait_idle(int max_ms);
|
|||||||
#endif
|
#endif
|
||||||
#endif // CONFIG_ESP_HOSTED_ENABLED
|
#endif // CONFIG_ESP_HOSTED_ENABLED
|
||||||
|
|
||||||
|
#ifdef min
|
||||||
|
#undef min
|
||||||
|
#endif
|
||||||
|
#ifdef max
|
||||||
|
#undef max
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif // CONFIG_BT_NIMBLE_ENABLED
|
#endif // CONFIG_BT_NIMBLE_ENABLED
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
// SPDX-License-Identifier: Apache-2.0
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
#include <driver/gpio.h>
|
#include <driver/gpio.h>
|
||||||
|
#include <soc/soc.h>
|
||||||
|
#include <soc/gpio_periph.h>
|
||||||
|
#include <soc/gpio_struct.h>
|
||||||
|
#include <soc/io_mux_reg.h>
|
||||||
|
|
||||||
#include <tactility/driver.h>
|
#include <tactility/driver.h>
|
||||||
#include <tactility/drivers/esp32_gpio.h>
|
#include <tactility/drivers/esp32_gpio.h>
|
||||||
@@ -65,30 +69,34 @@ static error_t set_flags(GpioDescriptor* descriptor, gpio_flags_t flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static error_t get_flags(GpioDescriptor* descriptor, gpio_flags_t* flags) {
|
static error_t get_flags(GpioDescriptor* descriptor, gpio_flags_t* flags) {
|
||||||
gpio_io_config_t esp_config;
|
auto pin = static_cast<gpio_num_t>(descriptor->pin);
|
||||||
if (gpio_get_io_config(static_cast<gpio_num_t>(descriptor->pin), &esp_config) != ESP_OK) {
|
|
||||||
return ERROR_RESOURCE;
|
|
||||||
}
|
|
||||||
|
|
||||||
gpio_flags_t output = 0;
|
gpio_flags_t output = 0;
|
||||||
|
|
||||||
if (esp_config.pu) {
|
// Read pull-up, pull-down, input-enable from IO MUX register
|
||||||
|
uint32_t pin_mux = REG_READ(GPIO_PIN_MUX_REG[pin]);
|
||||||
|
if (pin_mux & FUN_PU) {
|
||||||
output |= GPIO_FLAG_PULL_UP;
|
output |= GPIO_FLAG_PULL_UP;
|
||||||
}
|
}
|
||||||
|
if (pin_mux & FUN_PD) {
|
||||||
if (esp_config.pd) {
|
|
||||||
output |= GPIO_FLAG_PULL_DOWN;
|
output |= GPIO_FLAG_PULL_DOWN;
|
||||||
}
|
}
|
||||||
|
if (pin_mux & FUN_IE) {
|
||||||
if (esp_config.ie) {
|
|
||||||
output |= GPIO_FLAG_DIRECTION_INPUT;
|
output |= GPIO_FLAG_DIRECTION_INPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (esp_config.oe) {
|
// Read output-enable from GPIO matrix
|
||||||
|
bool oe = false;
|
||||||
|
if (pin < 32) {
|
||||||
|
oe = (GPIO.enable & (1UL << pin)) != 0;
|
||||||
|
} else {
|
||||||
|
oe = (GPIO.enable1.data & (1UL << (pin - 32))) != 0;
|
||||||
|
}
|
||||||
|
if (oe) {
|
||||||
output |= GPIO_FLAG_DIRECTION_OUTPUT;
|
output |= GPIO_FLAG_DIRECTION_OUTPUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (esp_config.oe_inv) {
|
// Read output-inversion from GPIO matrix
|
||||||
|
if (GPIO.func_out_sel_cfg[pin].inv_sel) {
|
||||||
output |= GPIO_FLAG_ACTIVE_LOW;
|
output |= GPIO_FLAG_ACTIVE_LOW;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
#include <driver/i2c_master.h>
|
#include <driver/i2c_master.h>
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <cstring>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
#include <tactility/error_esp32.h>
|
#include <tactility/error_esp32.h>
|
||||||
#include <tactility/driver.h>
|
#include <tactility/driver.h>
|
||||||
@@ -39,12 +41,48 @@ struct Esp32I2cMasterInternal {
|
|||||||
#define lock(data) mutex_lock(&data->mutex);
|
#define lock(data) mutex_lock(&data->mutex);
|
||||||
#define unlock(data) mutex_unlock(&data->mutex);
|
#define unlock(data) mutex_unlock(&data->mutex);
|
||||||
|
|
||||||
|
struct MyI2cMasterDev {
|
||||||
|
void* master_bus;
|
||||||
|
uint16_t device_address;
|
||||||
|
};
|
||||||
|
|
||||||
|
static esp_err_t my_i2c_master_device_change_address(i2c_master_dev_handle_t i2c_dev, uint16_t new_device_address, int timeout_ms) {
|
||||||
|
if (i2c_dev == nullptr) return ESP_ERR_INVALID_ARG;
|
||||||
|
auto* dev = reinterpret_cast<MyI2cMasterDev*>(i2c_dev);
|
||||||
|
dev->device_address = new_device_address;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t my_i2c_master_transmit_multi_buffer(i2c_master_dev_handle_t dev_handle, uint8_t reg, const uint8_t* data, uint16_t data_size, int timeout_ms) {
|
||||||
|
uint32_t total_size = data_size + 1;
|
||||||
|
if (total_size <= 128) {
|
||||||
|
uint8_t temp_buf[128];
|
||||||
|
temp_buf[0] = reg;
|
||||||
|
if (data_size > 0 && data != nullptr) {
|
||||||
|
std::memcpy(temp_buf + 1, data, data_size);
|
||||||
|
}
|
||||||
|
return i2c_master_transmit(dev_handle, temp_buf, total_size, timeout_ms);
|
||||||
|
} else {
|
||||||
|
uint8_t* temp_buf = (uint8_t*)std::malloc(total_size);
|
||||||
|
if (temp_buf == nullptr) {
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
temp_buf[0] = reg;
|
||||||
|
if (data_size > 0 && data != nullptr) {
|
||||||
|
std::memcpy(temp_buf + 1, data, data_size);
|
||||||
|
}
|
||||||
|
esp_err_t ret = i2c_master_transmit(dev_handle, temp_buf, total_size, timeout_ms);
|
||||||
|
std::free(temp_buf);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Switches the device's target address only when it differs from the currently configured one.
|
// Switches the device's target address only when it differs from the currently configured one.
|
||||||
static esp_err_t ensure_address(Esp32I2cMasterInternal* driver_data, uint8_t address, int timeout_ms) {
|
static esp_err_t ensure_address(Esp32I2cMasterInternal* driver_data, uint8_t address, int timeout_ms) {
|
||||||
if (driver_data->current_address == address) {
|
if (driver_data->current_address == address) {
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
esp_err_t esp_error = i2c_master_device_change_address(driver_data->dev_handle, address, timeout_ms);
|
esp_err_t esp_error = my_i2c_master_device_change_address(driver_data->dev_handle, address, timeout_ms);
|
||||||
if (esp_error == ESP_OK) {
|
if (esp_error == ESP_OK) {
|
||||||
driver_data->current_address = address;
|
driver_data->current_address = address;
|
||||||
}
|
}
|
||||||
@@ -149,11 +187,7 @@ static error_t write_register(Device* device, uint8_t address, uint8_t reg, cons
|
|||||||
if (esp_error != ESP_OK) {
|
if (esp_error != ESP_OK) {
|
||||||
LOG_E(TAG, "change_address(0x%02X) failed: %s", address, esp_err_to_name(esp_error));
|
LOG_E(TAG, "change_address(0x%02X) failed: %s", address, esp_err_to_name(esp_error));
|
||||||
} else {
|
} else {
|
||||||
i2c_master_transmit_multi_buffer_info_t buffers[2] = {
|
esp_error = my_i2c_master_transmit_multi_buffer(driver_data->dev_handle, reg, data, data_size, timeout_ms);
|
||||||
{.write_buffer = ®, .buffer_size = 1},
|
|
||||||
{.write_buffer = data, .buffer_size = data_size}
|
|
||||||
};
|
|
||||||
esp_error = i2c_master_multi_buffer_transmit(driver_data->dev_handle, buffers, 2, timeout_ms);
|
|
||||||
if (esp_error != ESP_OK) {
|
if (esp_error != ESP_OK) {
|
||||||
LOG_E(TAG, "write_register(0x%02X, reg=0x%02X) failed: %s", address, reg, esp_err_to_name(esp_error));
|
LOG_E(TAG, "write_register(0x%02X, reg=0x%02X) failed: %s", address, reg, esp_err_to_name(esp_error));
|
||||||
}
|
}
|
||||||
@@ -212,7 +246,6 @@ static error_t start(Device* device) {
|
|||||||
.trans_queue_depth = 0,
|
.trans_queue_depth = 0,
|
||||||
.flags = {
|
.flags = {
|
||||||
.enable_internal_pullup = ((sda_spec.flags & GPIO_FLAG_PULL_UP) != 0) || ((scl_spec.flags & GPIO_FLAG_PULL_UP) != 0),
|
.enable_internal_pullup = ((sda_spec.flags & GPIO_FLAG_PULL_UP) != 0) || ((scl_spec.flags & GPIO_FLAG_PULL_UP) != 0),
|
||||||
.allow_pd = 0,
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -307,7 +340,7 @@ extern Module platform_esp32_module;
|
|||||||
|
|
||||||
Driver esp32_i2c_master_driver = {
|
Driver esp32_i2c_master_driver = {
|
||||||
.name = "esp32_i2c_master",
|
.name = "esp32_i2c_master",
|
||||||
.compatible = (const char*[]) { "espressif,esp32-i2c-master", nullptr },
|
.compatible = (const char*[]) { "espressif,esp32-i2c", "espressif,esp32-i2c-master", nullptr },
|
||||||
.start_device = start,
|
.start_device = start,
|
||||||
.stop_device = stop,
|
.stop_device = stop,
|
||||||
.api = &ESP32_I2C_MASTER_API,
|
.api = &ESP32_I2C_MASTER_API,
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include <tactility/drivers/esp32_i2s.h>
|
#include <tactility/drivers/esp32_i2s.h>
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#define TAG "esp32_i2s"
|
#define TAG "esp32_i2s"
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,11 @@
|
|||||||
#include <freertos/task.h>
|
#include <freertos/task.h>
|
||||||
#include <sdmmc_cmd.h>
|
#include <sdmmc_cmd.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
#ifndef SDMMC_SLOT_FLAG_UHS1
|
||||||
|
#define SDMMC_SLOT_FLAG_UHS1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#if SOC_SD_PWR_CTRL_SUPPORTED
|
#if SOC_SD_PWR_CTRL_SUPPORTED
|
||||||
#include <sd_pwr_ctrl_by_on_chip_ldo.h>
|
#include <sd_pwr_ctrl_by_on_chip_ldo.h>
|
||||||
|
|||||||
@@ -101,7 +101,6 @@ static error_t start(Device* device) {
|
|||||||
.data5_io_num = GPIO_NUM_NC,
|
.data5_io_num = GPIO_NUM_NC,
|
||||||
.data6_io_num = GPIO_NUM_NC,
|
.data6_io_num = GPIO_NUM_NC,
|
||||||
.data7_io_num = GPIO_NUM_NC,
|
.data7_io_num = GPIO_NUM_NC,
|
||||||
.data_io_default_level = false,
|
|
||||||
.max_transfer_sz = dts_config->max_transfer_size,
|
.max_transfer_sz = dts_config->max_transfer_size,
|
||||||
.flags = 0,
|
.flags = 0,
|
||||||
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
|
.isr_cpu_id = ESP_INTR_CPU_AFFINITY_AUTO,
|
||||||
|
|||||||
@@ -13,6 +13,7 @@
|
|||||||
#include <tactility/drivers/esp32_gpio_helpers.h>
|
#include <tactility/drivers/esp32_gpio_helpers.h>
|
||||||
|
|
||||||
#include <new>
|
#include <new>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#define TAG "esp32_uart"
|
#define TAG "esp32_uart"
|
||||||
|
|
||||||
@@ -264,10 +265,6 @@ static error_t open(Device* device) {
|
|||||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, // Flow control is not yet exposed via UartConfig
|
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE, // Flow control is not yet exposed via UartConfig
|
||||||
.rx_flow_ctrl_thresh = 0,
|
.rx_flow_ctrl_thresh = 0,
|
||||||
.source_clk = UART_SCLK_DEFAULT,
|
.source_clk = UART_SCLK_DEFAULT,
|
||||||
.flags = {
|
|
||||||
.allow_pd = 0,
|
|
||||||
.backup_before_sleep = 0
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (dts_config->pin_cts.gpio_controller != nullptr || dts_config->pin_rts.gpio_controller != nullptr) {
|
if (dts_config->pin_cts.gpio_controller != nullptr || dts_config->pin_rts.gpio_controller != nullptr) {
|
||||||
|
|||||||
@@ -70,8 +70,6 @@ static error_t start_device(struct Device* device) {
|
|||||||
.root_port_unpowered = false,
|
.root_port_unpowered = false,
|
||||||
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
.intr_flags = ESP_INTR_FLAG_LEVEL1,
|
||||||
.enum_filter_cb = nullptr,
|
.enum_filter_cb = nullptr,
|
||||||
.fifo_settings_custom = {},
|
|
||||||
.peripheral_map = cfg->peripheral_map,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
esp_err_t ret = usb_host_install(&host_cfg);
|
esp_err_t ret = usb_host_install(&host_cfg);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <Tactility/PartitionsEsp.h>
|
#include <Tactility/PartitionsEsp.h>
|
||||||
#include <Tactility/Logger.h>
|
#include <Tactility/Logger.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
#include <esp_vfs_fat.h>
|
#include <esp_vfs_fat.h>
|
||||||
#include <nvs_flash.h>
|
#include <nvs_flash.h>
|
||||||
|
|||||||
@@ -344,9 +344,22 @@ void run(const Configuration& config, Module* dtsModules[], DtsDevice dtsDevices
|
|||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
initEsp();
|
initEsp();
|
||||||
#endif
|
#endif
|
||||||
file::setFindLockFunction(file::findLock);
|
|
||||||
settings::initTimeZone();
|
settings::initTimeZone();
|
||||||
hal::init(*config.hardware);
|
hal::init(*config.hardware);
|
||||||
|
|
||||||
|
LOGGER.info("DEBUG: Listing /sdcard");
|
||||||
|
file::listDirectory("/sdcard", [](const dirent& entry) {
|
||||||
|
LOGGER.info("DEBUG: /sdcard entry: {} (dir={})", entry.d_name, entry.d_type == DT_DIR);
|
||||||
|
});
|
||||||
|
if (file::isDirectory("/sdcard/app")) {
|
||||||
|
LOGGER.info("DEBUG: Listing /sdcard/app");
|
||||||
|
file::listDirectory("/sdcard/app", [](const dirent& entry) {
|
||||||
|
LOGGER.info("DEBUG: /sdcard/app entry: {}", entry.d_name);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
LOGGER.info("DEBUG: /sdcard/app is NOT a directory");
|
||||||
|
}
|
||||||
|
|
||||||
network::ntp::init();
|
network::ntp::init();
|
||||||
bluetooth::systemStart();
|
bluetooth::systemStart();
|
||||||
|
|
||||||
|
|||||||
@@ -36,9 +36,7 @@ static bool untarFile(minitar* mp, const minitar_entry* entry, const std::string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Note: fchmod() doesn't exist on ESP-IDF and chmod() does nothing on that platform
|
// Note: fchmod() doesn't exist on ESP-IDF and chmod() does nothing on that platform
|
||||||
if (chmod(absolute_path.c_str(), entry->metadata.mode) < 0) {
|
chmod(absolute_path.c_str(), entry->metadata.mode);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,14 @@
|
|||||||
#include <host/ble_gatt.h>
|
#include <host/ble_gatt.h>
|
||||||
#include <host/ble_hs.h>
|
#include <host/ble_hs.h>
|
||||||
#include <host/ble_uuid.h>
|
#include <host/ble_uuid.h>
|
||||||
|
|
||||||
|
#ifdef min
|
||||||
|
#undef min
|
||||||
|
#endif
|
||||||
|
#ifdef max
|
||||||
|
#undef max
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <esp_timer.h>
|
#include <esp_timer.h>
|
||||||
#include <freertos/FreeRTOS.h>
|
#include <freertos/FreeRTOS.h>
|
||||||
#include <freertos/queue.h>
|
#include <freertos/queue.h>
|
||||||
|
|||||||
@@ -126,11 +126,14 @@ esp_err_t DevelopmentService::handleAppInstall(httpd_req_t* request) {
|
|||||||
// Skip newline after reading boundary
|
// Skip newline after reading boundary
|
||||||
auto content_headers_data = network::receiveTextUntil(request, "\r\n\r\n");
|
auto content_headers_data = network::receiveTextUntil(request, "\r\n\r\n");
|
||||||
content_left -= content_headers_data.length();
|
content_left -= content_headers_data.length();
|
||||||
auto content_headers = string::split(content_headers_data, "\r\n")
|
auto raw_headers = string::split(content_headers_data, "\r\n");
|
||||||
| std::views::filter([](const std::string& line) {
|
std::vector<std::string> content_headers;
|
||||||
return line.length() > 0;
|
content_headers.reserve(raw_headers.size());
|
||||||
})
|
for (const auto& line : raw_headers) {
|
||||||
| std::ranges::to<std::vector>();
|
if (line.length() > 0) {
|
||||||
|
content_headers.push_back(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto content_disposition_map = network::parseContentDisposition(content_headers);
|
auto content_disposition_map = network::parseContentDisposition(content_headers);
|
||||||
if (content_disposition_map.empty()) {
|
if (content_disposition_map.empty()) {
|
||||||
|
|||||||
@@ -68,7 +68,9 @@ static const char* getChipModelName(esp_chip_model_t model) {
|
|||||||
case CHIP_ESP32C6: return "ESP32-C6";
|
case CHIP_ESP32C6: return "ESP32-C6";
|
||||||
case CHIP_ESP32H2: return "ESP32-H2";
|
case CHIP_ESP32H2: return "ESP32-H2";
|
||||||
case CHIP_ESP32P4: return "ESP32-P4";
|
case CHIP_ESP32P4: return "ESP32-P4";
|
||||||
|
#if defined(CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION) || defined(CONFIG_IDF_TARGET_ESP32C5_MP_VERSION)
|
||||||
case CHIP_ESP32C5: return "ESP32-C5";
|
case CHIP_ESP32C5: return "ESP32-C5";
|
||||||
|
#endif
|
||||||
case CHIP_ESP32C61: return "ESP32-C61";
|
case CHIP_ESP32C61: return "ESP32-C61";
|
||||||
default: return "Unknown";
|
default: return "Unknown";
|
||||||
}
|
}
|
||||||
@@ -1339,11 +1341,14 @@ esp_err_t WebServerService::handleApiAppsInstall(httpd_req_t* request) {
|
|||||||
content_left -= content_headers_data.length();
|
content_left -= content_headers_data.length();
|
||||||
|
|
||||||
// Split headers into lines and filter empty ones
|
// Split headers into lines and filter empty ones
|
||||||
auto content_headers = string::split(content_headers_data, "\r\n")
|
auto raw_headers = string::split(content_headers_data, "\r\n");
|
||||||
| std::views::filter([](const std::string& line) {
|
std::vector<std::string> content_headers;
|
||||||
return line.length() > 0;
|
content_headers.reserve(raw_headers.size());
|
||||||
})
|
for (const auto& line : raw_headers) {
|
||||||
| std::ranges::to<std::vector>();
|
if (line.length() > 0) {
|
||||||
|
content_headers.push_back(line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto content_disposition_map = network::parseContentDisposition(content_headers);
|
auto content_disposition_map = network::parseContentDisposition(content_headers);
|
||||||
if (content_disposition_map.empty()) {
|
if (content_disposition_map.empty()) {
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <symbols/esp_http_client.h>
|
#include <symbols/esp_http_client.h>
|
||||||
|
|
||||||
#include <esp_http_client.h>
|
#include <esp_http_client.h>
|
||||||
|
#include <esp_idf_version.h>
|
||||||
|
|
||||||
const esp_elfsym esp_http_client_symbols[] = {
|
const esp_elfsym esp_http_client_symbols[] = {
|
||||||
ESP_ELFSYM_EXPORT(esp_http_client_init),
|
ESP_ELFSYM_EXPORT(esp_http_client_init),
|
||||||
@@ -23,11 +24,15 @@ const esp_elfsym esp_http_client_symbols[] = {
|
|||||||
ESP_ELFSYM_EXPORT(esp_http_client_get_user_data),
|
ESP_ELFSYM_EXPORT(esp_http_client_get_user_data),
|
||||||
ESP_ELFSYM_EXPORT(esp_http_client_set_user_data),
|
ESP_ELFSYM_EXPORT(esp_http_client_set_user_data),
|
||||||
ESP_ELFSYM_EXPORT(esp_http_client_get_errno),
|
ESP_ELFSYM_EXPORT(esp_http_client_get_errno),
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)
|
||||||
ESP_ELFSYM_EXPORT(esp_http_client_get_and_clear_last_tls_error),
|
ESP_ELFSYM_EXPORT(esp_http_client_get_and_clear_last_tls_error),
|
||||||
|
#endif
|
||||||
ESP_ELFSYM_EXPORT(esp_http_client_set_method),
|
ESP_ELFSYM_EXPORT(esp_http_client_set_method),
|
||||||
ESP_ELFSYM_EXPORT(esp_http_client_set_timeout_ms),
|
ESP_ELFSYM_EXPORT(esp_http_client_set_timeout_ms),
|
||||||
ESP_ELFSYM_EXPORT(esp_http_client_delete_header),
|
ESP_ELFSYM_EXPORT(esp_http_client_delete_header),
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)
|
||||||
ESP_ELFSYM_EXPORT(esp_http_client_delete_all_headers),
|
ESP_ELFSYM_EXPORT(esp_http_client_delete_all_headers),
|
||||||
|
#endif
|
||||||
ESP_ELFSYM_EXPORT(esp_http_client_open),
|
ESP_ELFSYM_EXPORT(esp_http_client_open),
|
||||||
ESP_ELFSYM_EXPORT(esp_http_client_write),
|
ESP_ELFSYM_EXPORT(esp_http_client_write),
|
||||||
ESP_ELFSYM_EXPORT(esp_http_client_fetch_headers),
|
ESP_ELFSYM_EXPORT(esp_http_client_fetch_headers),
|
||||||
|
|||||||
@@ -37,11 +37,13 @@
|
|||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
|
#include <esp_idf_version.h>
|
||||||
#include <esp_random.h>
|
#include <esp_random.h>
|
||||||
#include <esp_sntp.h>
|
#include <esp_sntp.h>
|
||||||
#include <esp_netif.h>
|
#include <esp_netif.h>
|
||||||
#include <esp_heap_caps.h>
|
#include <esp_heap_caps.h>
|
||||||
#include <esp_timer.h>
|
#include <esp_timer.h>
|
||||||
|
#include <lvgl.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <lwip/sockets.h>
|
#include <lwip/sockets.h>
|
||||||
#include <lwip/netdb.h>
|
#include <lwip/netdb.h>
|
||||||
@@ -263,7 +265,9 @@ const esp_elfsym main_symbols[] {
|
|||||||
ESP_ELFSYM_EXPORT(tolower),
|
ESP_ELFSYM_EXPORT(tolower),
|
||||||
ESP_ELFSYM_EXPORT(toupper),
|
ESP_ELFSYM_EXPORT(toupper),
|
||||||
// ESP-IDF
|
// ESP-IDF
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)
|
||||||
ESP_ELFSYM_EXPORT(esp_log),
|
ESP_ELFSYM_EXPORT(esp_log),
|
||||||
|
#endif
|
||||||
ESP_ELFSYM_EXPORT(esp_log_write),
|
ESP_ELFSYM_EXPORT(esp_log_write),
|
||||||
ESP_ELFSYM_EXPORT(esp_log_timestamp),
|
ESP_ELFSYM_EXPORT(esp_log_timestamp),
|
||||||
ESP_ELFSYM_EXPORT(esp_err_to_name),
|
ESP_ELFSYM_EXPORT(esp_err_to_name),
|
||||||
@@ -373,6 +377,13 @@ const esp_elfsym main_symbols[] {
|
|||||||
// tt::lvgl
|
// tt::lvgl
|
||||||
ESP_ELFSYM_EXPORT(tt_lvgl_spinner_create),
|
ESP_ELFSYM_EXPORT(tt_lvgl_spinner_create),
|
||||||
|
|
||||||
|
// LVGL APIs needed by side-loaded apps that render into canvases.
|
||||||
|
ESP_ELFSYM_EXPORT(lv_canvas_create),
|
||||||
|
ESP_ELFSYM_EXPORT(lv_canvas_set_buffer),
|
||||||
|
ESP_ELFSYM_EXPORT(lv_obj_invalidate),
|
||||||
|
ESP_ELFSYM_EXPORT(lv_display_get_horizontal_resolution),
|
||||||
|
ESP_ELFSYM_EXPORT(lv_display_get_vertical_resolution),
|
||||||
|
|
||||||
// stdio.h
|
// stdio.h
|
||||||
ESP_ELFSYM_EXPORT(rename),
|
ESP_ELFSYM_EXPORT(rename),
|
||||||
ESP_ELFSYM_EXPORT(rewind),
|
ESP_ELFSYM_EXPORT(rewind),
|
||||||
@@ -423,7 +434,9 @@ const esp_elfsym main_symbols[] {
|
|||||||
ESP_ELFSYM_EXPORT(i2s_channel_read),
|
ESP_ELFSYM_EXPORT(i2s_channel_read),
|
||||||
ESP_ELFSYM_EXPORT(i2s_channel_register_event_callback),
|
ESP_ELFSYM_EXPORT(i2s_channel_register_event_callback),
|
||||||
ESP_ELFSYM_EXPORT(i2s_channel_preload_data),
|
ESP_ELFSYM_EXPORT(i2s_channel_preload_data),
|
||||||
|
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 4, 0)
|
||||||
ESP_ELFSYM_EXPORT(i2s_channel_tune_rate),
|
ESP_ELFSYM_EXPORT(i2s_channel_tune_rate),
|
||||||
|
#endif
|
||||||
// driver/i2s_std.h
|
// driver/i2s_std.h
|
||||||
ESP_ELFSYM_EXPORT(i2s_channel_init_std_mode),
|
ESP_ELFSYM_EXPORT(i2s_channel_init_std_mode),
|
||||||
ESP_ELFSYM_EXPORT(i2s_channel_reconfig_std_clock),
|
ESP_ELFSYM_EXPORT(i2s_channel_reconfig_std_clock),
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace tt {
|
|||||||
#ifdef CONFIG_ESP_WIFI_ENABLED
|
#ifdef CONFIG_ESP_WIFI_ENABLED
|
||||||
|
|
||||||
static CpuAffinity getEspWifiAffinity() {
|
static CpuAffinity getEspWifiAffinity() {
|
||||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 1
|
#if CONFIG_SOC_CPU_CORES_NUM == 1
|
||||||
return 0;
|
return 0;
|
||||||
#elif defined(CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0)
|
#elif defined(CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -28,7 +28,7 @@ static CpuAffinity getEspWifiAffinity() {
|
|||||||
|
|
||||||
// Warning: Must watch ESP WiFi, as this task is used by WiFi
|
// Warning: Must watch ESP WiFi, as this task is used by WiFi
|
||||||
static CpuAffinity getEspMainSchedulerAffinity() {
|
static CpuAffinity getEspMainSchedulerAffinity() {
|
||||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 1
|
#if CONFIG_SOC_CPU_CORES_NUM == 1
|
||||||
return 0;
|
return 0;
|
||||||
#elif defined(CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0)
|
#elif defined(CONFIG_ESP_WIFI_TASK_PINNED_TO_CORE_0)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -41,7 +41,7 @@ static CpuAffinity getEspMainSchedulerAffinity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static CpuAffinity getFreeRtosTimerAffinity() {
|
static CpuAffinity getFreeRtosTimerAffinity() {
|
||||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 1
|
#if CONFIG_SOC_CPU_CORES_NUM == 1
|
||||||
return 0;
|
return 0;
|
||||||
#elif defined(CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY)
|
#elif defined(CONFIG_FREERTOS_TIMER_TASK_NO_AFFINITY)
|
||||||
return None;
|
return None;
|
||||||
@@ -50,11 +50,11 @@ static CpuAffinity getFreeRtosTimerAffinity() {
|
|||||||
#elif defined(CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1)
|
#elif defined(CONFIG_FREERTOS_TIMER_TASK_AFFINITY_CPU1)
|
||||||
return 1;
|
return 1;
|
||||||
#else
|
#else
|
||||||
static_assert(false);
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 1
|
#if CONFIG_SOC_CPU_CORES_NUM == 1
|
||||||
static const CpuAffinityConfiguration esp = {
|
static const CpuAffinityConfiguration esp = {
|
||||||
.system = 0,
|
.system = 0,
|
||||||
.graphics = 0,
|
.graphics = 0,
|
||||||
@@ -63,7 +63,7 @@ static const CpuAffinityConfiguration esp = {
|
|||||||
.apps = 0,
|
.apps = 0,
|
||||||
.timer = getFreeRtosTimerAffinity()
|
.timer = getFreeRtosTimerAffinity()
|
||||||
};
|
};
|
||||||
#elif CONFIG_FREERTOS_NUMBER_OF_CORES == 2
|
#elif CONFIG_SOC_CPU_CORES_NUM == 2
|
||||||
static const CpuAffinityConfiguration esp = {
|
static const CpuAffinityConfiguration esp = {
|
||||||
.system = 0,
|
.system = 0,
|
||||||
.graphics = 1,
|
.graphics = 1,
|
||||||
@@ -94,7 +94,7 @@ static const CpuAffinityConfiguration simulator = {
|
|||||||
const CpuAffinityConfiguration& getCpuAffinityConfiguration() {
|
const CpuAffinityConfiguration& getCpuAffinityConfiguration() {
|
||||||
#ifdef ESP_PLATFORM
|
#ifdef ESP_PLATFORM
|
||||||
|
|
||||||
#if CONFIG_FREERTOS_NUMBER_OF_CORES == 2
|
#if CONFIG_SOC_CPU_CORES_NUM == 2
|
||||||
// WiFi uses the main dispatcher to defer operations in the background
|
// WiFi uses the main dispatcher to defer operations in the background
|
||||||
assert(esp.wifi == esp.mainDispatcher);
|
assert(esp.wifi == esp.mainDispatcher);
|
||||||
#endif // CORES
|
#endif // CORES
|
||||||
|
|||||||
Reference in New Issue
Block a user