Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions Buildscripts/TactilitySDK/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,7 @@ idf_component_register(
"Libraries/TactilityFreeRtos/include"
"Libraries/lvgl/include"
"Modules/lvgl-module/include"
"Drivers/bm8563-module/include"
"Drivers/bmi270-module/include"
"Drivers/mpu6886-module/include"
"Drivers/pi4ioe5v6408-module/include"
"Drivers/qmi8658-module/include"
"Drivers/rx8130ce-module/include"
# DRIVER_INCLUDE_DIRS_PLACEHOLDER
REQUIRES esp_timer
)

Expand Down
7 changes: 1 addition & 6 deletions Buildscripts/TactilitySDK/TactilitySDK.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,7 @@ macro(tactility_project project_name)

set(COMPONENTS
TactilityFreeRtos
bm8563-module
bmi270-module
mpu6886-module
pi4ioe5v6408-module
qmi8658-module
rx8130ce-module
# DRIVER_COMPONENTS_PLACEHOLDER
)

endmacro()
69 changes: 59 additions & 10 deletions Buildscripts/release-sdk.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ def write_module_cmakelists(path, content):
with open(path, 'w') as f:
f.write(content)

def driver_is_available(driver_name):
"""
Some drivers only build for certain chip targets (e.g. sc2356-module is ESP32-P4 only,
since it depends on esp_video/esp_cam_sensor/PPA which are themselves chip-restricted).
Build output presence is the single source of truth for "does this driver support the
current target" - no separate manifest to keep in sync with the real CMakeLists.txt
REQUIRES/Kconfig guards.
"""
binary_pattern = f'build/esp-idf/{driver_name}/lib{driver_name}.a'
return bool(glob.glob(binary_pattern))

def add_driver(target_path, driver_name):
mappings = get_driver_mappings(driver_name)
map_copy(mappings, target_path)
Expand All @@ -100,6 +111,44 @@ def add_module(target_path, module_name):
cmakelists_content = create_module_cmakelists(module_name)
write_module_cmakelists(os.path.join(target_path, f"Modules/{module_name}/CMakeLists.txt"), cmakelists_content)

def discover_all_drivers():
"""
Discover all *-module directories under Drivers/ (not Modules/ - those are handled
separately via add_module). Sorted for deterministic output across OS/filesystem order.
"""
pattern = os.path.join('Drivers', '*-module')
return sorted(
os.path.basename(p) for p in glob.glob(pattern) if os.path.isdir(p)
)

def generate_tactility_sdk_cmake(target_path, available_drivers):
src = os.path.join('Buildscripts', 'TactilitySDK', 'TactilitySDK.cmake')
with open(src) as f:
content = f.read()
placeholder = " # DRIVER_COMPONENTS_PLACEHOLDER"
assert placeholder in content, \
f"Placeholder '{placeholder.strip()}' not found in {src} - template drifted, generator needs updating"
components = "\n".join(f" {d}" for d in available_drivers)
new_content = content.replace(placeholder, components)
assert placeholder not in new_content, \
f"Placeholder '{placeholder.strip()}' still present after replacement in {src}"
with open(os.path.join(target_path, 'TactilitySDK.cmake'), 'w') as f:
f.write(new_content)

def generate_tactility_sdk_top_cmakelists(target_path, available_drivers):
src = os.path.join('Buildscripts', 'TactilitySDK', 'CMakeLists.txt')
with open(src) as f:
content = f.read()
placeholder = " # DRIVER_INCLUDE_DIRS_PLACEHOLDER"
assert placeholder in content, \
f"Placeholder '{placeholder.strip()}' not found in {src} - template drifted, generator needs updating"
include_dirs = "\n".join(f' "Drivers/{d}/include"' for d in available_drivers)
new_content = content.replace(placeholder, include_dirs)
assert placeholder not in new_content, \
f"Placeholder '{placeholder.strip()}' still present after replacement in {src}"
with open(os.path.join(target_path, 'CMakeLists.txt'), 'w') as f:
f.write(new_content)

def main():
if len(sys.argv) < 2:
print("Usage: release-sdk.py [target_path]")
Expand Down Expand Up @@ -136,9 +185,6 @@ def main():
# elf_loader
{'src': 'Libraries/elf_loader/elf_loader.cmake', 'dst': 'Libraries/elf_loader/'},
{'src': 'Libraries/elf_loader/license.txt', 'dst': 'Libraries/elf_loader/'},
# Final scripts
{'src': 'Buildscripts/TactilitySDK/TactilitySDK.cmake', 'dst': ''},
{'src': 'Buildscripts/TactilitySDK/CMakeLists.txt', 'dst': ''},
]

map_copy(mappings, target_path)
Expand All @@ -147,13 +193,16 @@ def main():
add_module(target_path, "lvgl-module")
add_module(target_path, "crypt-module")

# Drivers
add_driver(target_path, "bm8563-module")
add_driver(target_path, "bmi270-module")
add_driver(target_path, "mpu6886-module")
add_driver(target_path, "pi4ioe5v6408-module")
add_driver(target_path, "qmi8658-module")
add_driver(target_path, "rx8130ce-module")
# Drivers - only ones actually built for this target (chip-restricted drivers like
# sc2356-module won't have a .a outside ESP32-P4)
available_drivers = [d for d in discover_all_drivers() if driver_is_available(d)]
for driver_name in available_drivers:
add_driver(target_path, driver_name)

# Final scripts - generated (not copied verbatim) so COMPONENTS/INCLUDE_DIRS only list
# drivers actually available for this target
generate_tactility_sdk_cmake(target_path, available_drivers)
generate_tactility_sdk_top_cmakelists(target_path, available_drivers)

# Output ESP-IDF SDK version to file
esp_idf_version = os.environ.get("ESP_IDF_VERSION", "")
Expand Down
1 change: 1 addition & 0 deletions Devices/generic-esp32p4/devicetree.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ dependencies:
- Drivers/pi4ioe5v6408-module
- Drivers/qmi8658-module
- Drivers/rx8130ce-module
- Drivers/sc2356-module
dts: generic,esp32p4.dts
2 changes: 1 addition & 1 deletion Devices/m5stack-tab5/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,5 @@ file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
idf_component_register(
SRCS ${SOURCE_FILES}
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 esp_driver_i2c vfs fatfs ina226-module sc2356-module
)
26 changes: 26 additions & 0 deletions Devices/m5stack-tab5/Source/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#include <Tactility/hal/Configuration.h>

#include <esp_clock_output.h>

using namespace tt::hal;

static constexpr auto* TAG = "Tab5";
Expand Down Expand Up @@ -249,6 +251,29 @@ static error_t initMicrophone(::Device* i2c_controller) {
return error;
}

static esp_clock_output_mapping_handle_t camera_osc_handle = nullptr;

static void initCameraOsc() {
if (camera_osc_handle != nullptr) {
return;
}

// 24 MHz clock on GPIO 36 for the SC2356 MIPI CSI sensor, required before esp_video_init.
// Uses SPLL (480 MHz) via esp_clock_output with divider 20 = 24 MHz exactly.
// This avoids any LEDC clock source conflict with the display backlight.
if (esp_clock_output_start(CLKOUT_SIG_SPLL, GPIO_NUM_36, &camera_osc_handle) != ESP_OK) {
LOG_E(TAG, "Camera OSC clock output start failed");
return;
}
if (esp_clock_output_set_divider(camera_osc_handle, 20) != ESP_OK) {
LOG_E(TAG, "Camera OSC clock divider set failed");
esp_clock_output_stop(camera_osc_handle);
camera_osc_handle = nullptr;
return;
}
LOG_I(TAG, "Camera OSC 24MHz started on GPIO 36 (SPLL/20)");
}

static bool initBoot() {
auto* i2c0 = device_find_by_name("i2c0");
check(i2c0, "i2c0 not found");
Expand All @@ -258,6 +283,7 @@ static bool initBoot() {
auto* io_expander1 = device_find_by_name("io_expander1");
check(io_expander1, "io_expander1 not found");

initCameraOsc();
initExpander0(io_expander0);
initExpander1(io_expander1);

Expand Down
4 changes: 4 additions & 0 deletions Devices/m5stack-tab5/device.properties
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,7 @@ sdkconfig.CONFIG_CACHE_L2_CACHE_256KB=y
sdkconfig.CONFIG_LVGL_PORT_ENABLE_PPA=y
sdkconfig.CONFIG_LV_DRAW_BUF_ALIGN=64
sdkconfig.CONFIG_LV_DEF_REFR_PERIOD=15
# SC202CS (SC2356) MIPI CSI camera sensor + ISP pipeline (AE/AWB/demosaicing)
sdkconfig.CONFIG_CAMERA_SC202CS=y
sdkconfig.CONFIG_CAMERA_SC202CS_AUTO_DETECT_MIPI_INTERFACE_SENSOR=y
sdkconfig.CONFIG_ESP_VIDEO_ENABLE_ISP_PIPELINE_CONTROLLER=y
1 change: 1 addition & 0 deletions Devices/m5stack-tab5/devicetree.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ dependencies:
- Drivers/bmi270-module
- Drivers/ina226-module
- Drivers/rx8130ce-module
- Drivers/sc2356-module
dts: m5stack,tab5.dts
6 changes: 6 additions & 0 deletions Devices/m5stack-tab5/m5stack,tab5.dts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <bindings/ina226.h>
#include <bindings/pi4ioe5v6408.h>
#include <bindings/rx8130ce.h>
#include <bindings/sc2356.h>

/ {
compatible = "root";
Expand Down Expand Up @@ -60,6 +61,11 @@
reg = <0x41>;
shunt-milliohms = <5>;
};

sc2356 {
compatible = "smartsens,sc2356";
reg = <0x36>;
};
};

port_a: grove0 {
Expand Down
2 changes: 2 additions & 0 deletions Documentation/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Tactility is an operating system for the ESP32 microcontroller family. It runs o

### Simulator (Linux/macOS, no ESP-IDF needed)

Simulator is not supported on Windows

```bash
cmake -B buildsim -G Ninja
ninja -C buildsim # build firmware + tests
Expand Down
18 changes: 5 additions & 13 deletions Drivers/bm8563-module/include/drivers/bm8563.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#pragma once

#include <stdint.h>
#include <tactility/drivers/rtc.h>
#include <tactility/error.h>

struct Device;
Expand All @@ -15,30 +16,21 @@ struct Bm8563Config {
uint8_t address;
};

struct Bm8563DateTime {
uint16_t year; // 2000–2199
uint8_t month; // 1–12
uint8_t day; // 1–31
uint8_t hour; // 0–23
uint8_t minute; // 0–59
uint8_t second; // 0–59
};

/**
* Read the current date and time from the RTC.
* @param[in] device bm8563 device
* @param[out] dt Pointer to Bm8563DateTime to populate
* @param[out] dt Pointer to RtcDateTime to populate
* @return ERROR_NONE on success
*/
error_t bm8563_get_datetime(struct Device* device, struct Bm8563DateTime* dt);
error_t bm8563_get_datetime(struct Device* device, struct RtcDateTime* dt);

/**
* Write the date and time to the RTC.
* @param[in] device bm8563 device
* @param[in] dt Pointer to Bm8563DateTime to write (year must be 2000–2199)
* @param[in] dt Pointer to RtcDateTime to write (year must be 2000–2199)
* @return ERROR_NONE on success, ERROR_INVALID_ARGUMENT if any field is out of range
*/
error_t bm8563_set_datetime(struct Device* device, const struct Bm8563DateTime* dt);
error_t bm8563_set_datetime(struct Device* device, const struct RtcDateTime* dt);

#ifdef __cplusplus
}
Expand Down
13 changes: 9 additions & 4 deletions Drivers/bm8563-module/source/bm8563.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ static error_t stop(Device* device) {

extern "C" {

error_t bm8563_get_datetime(Device* device, Bm8563DateTime* dt) {
error_t bm8563_get_datetime(Device* device, RtcDateTime* dt) {
auto* i2c_controller = device_get_parent(device);
auto address = GET_CONFIG(device)->address;

Expand All @@ -78,7 +78,7 @@ error_t bm8563_get_datetime(Device* device, Bm8563DateTime* dt) {
return ERROR_NONE;
}

error_t bm8563_set_datetime(Device* device, const Bm8563DateTime* dt) {
error_t bm8563_set_datetime(Device* device, const RtcDateTime* dt) {
if (dt->year < 2000 || dt->year > 2199 ||
dt->month < 1 || dt->month > 12 ||
dt->day < 1 || dt->day > 31 ||
Expand All @@ -104,13 +104,18 @@ error_t bm8563_set_datetime(Device* device, const Bm8563DateTime* dt) {
return i2c_controller_write_register(i2c_controller, address, REG_SECONDS, buf, sizeof(buf), I2C_TIMEOUT_TICKS);
}

RtcApi bm8563_rtc_api = {
.get_time = bm8563_get_datetime,
.set_time = bm8563_set_datetime
};

Driver bm8563_driver = {
.name = "bm8563",
.compatible = (const char*[]) { "belling,bm8563", nullptr },
.start_device = start,
.stop_device = stop,
.api = nullptr,
.device_type = nullptr,
.api = &bm8563_rtc_api,
.device_type = &RTC_TYPE,
.owner = &bm8563_module,
.internal = nullptr
};
Expand Down
4 changes: 1 addition & 3 deletions Drivers/bm8563-module/source/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ static error_t stop() {
return ERROR_NONE;
}

extern const ModuleSymbol bm8563_module_symbols[];

Module bm8563_module = {
.name = "bm8563",
.start = start,
.stop = stop,
.symbols = bm8563_module_symbols,
.symbols = nullptr,
.internal = nullptr
};

Expand Down
9 changes: 0 additions & 9 deletions Drivers/bm8563-module/source/symbols.c

This file was deleted.

18 changes: 5 additions & 13 deletions Drivers/rx8130ce-module/include/drivers/rx8130ce.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#pragma once

#include <stdint.h>
#include <tactility/drivers/rtc.h>
#include <tactility/error.h>

struct Device;
Expand All @@ -15,30 +16,21 @@ struct Rx8130ceConfig {
uint8_t address;
};

struct Rx8130ceDateTime {
uint16_t year; // 2000–2099
uint8_t month; // 1–12
uint8_t day; // 1–31
uint8_t hour; // 0–23
uint8_t minute; // 0–59
uint8_t second; // 0–59
};

/**
* Read the current date and time from the RTC.
* @param[in] device rx8130ce device
* @param[out] dt Pointer to Rx8130ceDateTime to populate
* @param[out] dt Pointer to RtcDateTime to populate
* @return ERROR_NONE on success, ERROR_INVALID_STATE if VLF is set (clock data unreliable)
*/
error_t rx8130ce_get_datetime(struct Device* device, struct Rx8130ceDateTime* dt);
error_t rx8130ce_get_datetime(struct Device* device, struct RtcDateTime* dt);

/**
* Write the date and time to the RTC.
* @param[in] device rx8130ce device
* @param[in] dt Pointer to Rx8130ceDateTime to write (year must be 2000–2099)
* @param[in] dt Pointer to RtcDateTime to write (year must be 2000–2099)
* @return ERROR_NONE on success, ERROR_INVALID_ARGUMENT if any field is out of range
*/
error_t rx8130ce_set_datetime(struct Device* device, const struct Rx8130ceDateTime* dt);
error_t rx8130ce_set_datetime(struct Device* device, const struct RtcDateTime* dt);

#ifdef __cplusplus
}
Expand Down
4 changes: 1 addition & 3 deletions Drivers/rx8130ce-module/source/module.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ static error_t stop() {
return ERROR_NONE;
}

extern const ModuleSymbol rx8130ce_module_symbols[];

Module rx8130ce_module = {
.name = "rx8130ce",
.start = start,
.stop = stop,
.symbols = rx8130ce_module_symbols,
.symbols = nullptr,
.internal = nullptr
};

Expand Down
Loading
Loading