Compare commits

..

No commits in common. "3220b1fd3a855c500e30a867650c5c513d45117d" and "8711521a36a7a164b11bdcacf1ff72a2f5979df0" have entirely different histories.

80 changed files with 486 additions and 339 deletions

View File

@ -45,7 +45,6 @@ def parse_binding(file_path: str, binding_dirs: list[str]) -> Binding:
required=details.get('required', False),
description=details.get('description', '').strip(),
default=details.get('default', None),
element_type=details.get('element-type', None),
)
properties_dict[name] = prop
filename = os.path.basename(file_path)

View File

@ -20,8 +20,10 @@ def write_define(file, define: DefineC, verbose: bool):
def get_device_node_name_safe(device: Device):
if device.node_name == "/":
return "root"
else:
return device.node_name.replace("-", "_")
name = device.node_name.replace("-", "_")
if device.node_address is not None:
name += "_" + device.node_address.replace("-", "_")
return name
def get_device_type_name(device: Device, bindings: list[Binding]):
device_binding = find_device_binding(device, bindings)
@ -80,7 +82,7 @@ def property_to_string(property: DeviceProperty, devices: list[Device]) -> str:
return "{ " + ",".join(value_list) + " }"
elif type == "phandle":
return find_phandle(devices, property.value)
elif type == "phandles":
elif type == "phandle-array":
value_list = list()
if isinstance(property.value, list):
for item in property.value:
@ -88,31 +90,16 @@ def property_to_string(property: DeviceProperty, devices: list[Device]) -> str:
value_list.append(property_to_string(DeviceProperty(name="", type=item.type, value=item.value), devices))
else:
value_list.append(str(item))
value_list.append("{ 0 }")
return "{ " + ",".join(value_list) + " }"
elif isinstance(property.value, str):
# If it's a string, assume it's a #define and show it as-is
return property.value
else:
raise Exception(f"Unsupported phandles type for {property.name} with value {property.value} ")
raise Exception(f"Unsupported phandle-array type for {property.value}")
else:
raise DevicetreeException(f"property_to_string() has an unsupported type: {type}")
def resolve_phandle_array_entries(device_property, devices):
"""Convert a phandle-array DTS property into a list of C initializer strings."""
entries = []
if device_property.type == "phandle-array":
items = device_property.value
elif device_property.type == "values":
items = [PropertyValue(type="values", value=device_property.value)]
else:
return []
for item in items:
if isinstance(item, PropertyValue):
entries.append(property_to_string(DeviceProperty(name="", type=item.type, value=item.value), devices))
else:
entries.append(str(item))
return entries
def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], devices: list[Device]) -> list:
compatible_property = find_device_property(device, "compatible")
if compatible_property is None:
@ -135,32 +122,11 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
if device_property.name not in binding_property_names:
raise DevicetreeException(f"Device '{device.node_name}' has invalid property '{device_property.name}'")
node_name = get_device_node_name_safe(device)
result = []
phandle_arrays = []
for binding_property in binding_properties:
# Allocate total expected configuration arguments
result = [0] * len(binding_properties)
for index, binding_property in enumerate(binding_properties):
device_property = find_device_property(device, binding_property.name)
if binding_property.type == "phandle-array":
if binding_property.element_type is None:
raise DevicetreeException(f"phandle-array property '{binding_property.name}' requires 'element-type' in binding")
prop_safe = binding_property.name.replace("-", "_")
array_var = f"{node_name}_{prop_safe}"
if device_property is not None:
entries = resolve_phandle_array_entries(device_property, devices)
phandle_arrays.append((array_var, binding_property.element_type, entries))
result.append(f"({binding_property.element_type}*){array_var}")
result.append(str(len(entries)))
elif binding_property.default is not None:
result.append("NULL")
result.append("0")
elif binding_property.required:
raise DevicetreeException(f"device {device.node_name} doesn't have property '{binding_property.name}'")
else:
result.append("NULL")
result.append("0")
continue
# No property specified in DTS, use binding defaults
if device_property is None:
if binding_property.default is not None:
temp_prop = DeviceProperty(
@ -168,38 +134,30 @@ def resolve_parameters_from_bindings(device: Device, bindings: list[Binding], de
type=binding_property.type,
value=binding_property.default
)
result.append(property_to_string(temp_prop, devices))
result[index] = property_to_string(temp_prop, devices)
elif binding_property.required:
raise DevicetreeException(f"device {device.node_name} doesn't have property '{binding_property.name}'")
elif binding_property.type == "bool" or binding_property.type == "boolean":
if binding_property.default == "true" or binding_property.default == None:
result.append("true")
else:
result.append("false")
result[index] = "true"
else: # Explicit or implied false
result[index] = "false"
else:
raise DevicetreeException(f"Device {device.node_name} doesn't have property '{binding_property.name}' and no default value is set")
else:
result.append(property_to_string(device_property, devices))
return result, phandle_arrays
result[index] = property_to_string(device_property, devices)
return result
def write_config(file, device: Device, bindings: list[Binding], devices: list[Device], type_name: str):
node_name = get_device_node_name_safe(device)
config_type = f"{type_name}_config_dt"
config_variable_name = f"{node_name}_config"
config_params, phandle_arrays = resolve_parameters_from_bindings(device, bindings, devices)
# Write phandle-array variables before the config struct
for array_var, element_type, entries in phandle_arrays:
entries_str = ", ".join(entries)
file.write(f"static {element_type} {array_var}[] = {{ {entries_str} }};\n")
file.write(f"static const {config_type} {config_variable_name}" " = {\n")
config_params = resolve_parameters_from_bindings(device, bindings, devices)
# Indent all params
for index, config_param in enumerate(config_params):
config_params[index] = f"\t{config_param}"
# Join with comma and newline
# Join with command and newline
if len(config_params) > 0:
config_params_joined = ",\n".join(config_params)
file.write(f"{config_params_joined}\n")

View File

@ -39,7 +39,6 @@ class BindingProperty:
required: bool
description: str
default: object = None
element_type: str = None
@dataclass
class Binding:

View File

@ -17,16 +17,16 @@ static struct Device root = {
.internal = NULL
};
static const generic_device_config_dt test_device_config = {
static const generic_device_config_dt test_device_0_config = {
0,
42,
"hello"
};
static struct Device test_device = {
static struct Device test_device_0 = {
.address = 0,
.name = "test-device",
.config = &test_device_config,
.config = &test_device_0_config,
.parent = &root,
.internal = NULL
};
@ -49,7 +49,7 @@ static struct Device bool_test_device = {
struct DtsDevice dts_devices[] = {
{ &root, "test,root", DTS_DEVICE_STATUS_OKAY },
{ &test_device, "test,generic-device", DTS_DEVICE_STATUS_OKAY },
{ &test_device_0, "test,generic-device", DTS_DEVICE_STATUS_OKAY },
{ &bool_test_device, "test,bool-device", DTS_DEVICE_STATUS_OKAY },
DTS_DEVICE_TERMINATOR
};

View File

@ -44,8 +44,9 @@
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 5 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -43,8 +43,9 @@
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
cs-gpios = <&gpio0 5 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 5 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -52,8 +52,9 @@
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
cs-gpios = <&gpio0 5 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 5 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -52,8 +52,9 @@
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 5 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -44,8 +44,9 @@
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 5 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -54,8 +54,9 @@
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 5 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -36,8 +36,9 @@
pin-miso = <&gpio0 41 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 48 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 42 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -45,8 +45,9 @@
pin-miso = <&gpio0 13 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 12 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 10 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -42,8 +42,9 @@
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 5 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -51,8 +51,9 @@
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 5 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -50,8 +50,9 @@
pin-miso = <&gpio0 4 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 5 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 7 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -50,8 +50,9 @@
pin-miso = <&gpio0 4 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 5 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 7 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -37,8 +37,9 @@
pin-miso = <&gpio0 4 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 5 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 0 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -53,8 +53,9 @@
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 5 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -53,8 +53,9 @@
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 5 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -37,8 +37,9 @@
pin-miso = <&gpio0 13 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 12 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 10 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -54,8 +54,9 @@
pin-miso = <&gpio0 19 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 5 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -8,7 +8,6 @@
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_uart.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/display_placeholder.h>
/ {
compatible = "root";
@ -65,13 +64,13 @@
spi1 {
compatible = "espressif,esp32-spi";
host = <SPI3_HOST>;
cs-gpios = <&gpio0 10 GPIO_FLAG_NONE>;
pin-mosi = <&gpio0 11 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 13 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 12 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 10 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -55,8 +55,9 @@
pin-miso = <&gpio0 13 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 12 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 10 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -11,6 +11,7 @@
static const auto LOGGER = tt::Logger("T-Deck");
// Power on
constexpr auto TDECK_POWERON_GPIO = GPIO_NUM_10;
static bool powerOn() {

View File

@ -45,8 +45,7 @@
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
cs-gpios = <&gpio0 12 GPIO_FLAG_NONE>, // Display
<&gpio0 39 GPIO_FLAG_NONE>, // SD card
<&gpio0 9 GPIO_FLAG_NONE>; // Radio
<&gpio0 39 GPIO_FLAG_NONE>; // SD card
pin-mosi = <&gpio0 41 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 38 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 40 GPIO_FLAG_NONE>;
@ -57,7 +56,7 @@
sdcard@1 {
compatible = "espressif,esp32-sdspi";
status = "disabled"; // Must be started after display
pin-cs = <&gpio0 39 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -6,8 +6,6 @@
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_sdmmc.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/display_placeholder.h>
#include <tactility/bindings/touch_placeholder.h>
/ {
compatible = "root";

View File

@ -35,21 +35,21 @@
spi0 {
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
cs-gpios = <&gpio0 36 GPIO_FLAG_NONE>, // Display
<&gpio0 21 GPIO_FLAG_NONE>; // SD card
cs-gpios = <&gpio0 21 GPIO_FLAG_NONE>, // SD card
<&gpio0 36 GPIO_FLAG_NONE>; // Display
pin-mosi = <&gpio0 34 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 33 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 35 GPIO_FLAG_NONE>;
display@0 {
compatible = "display-placeholder";
};
sdcard@1 {
sdcard@0 {
compatible = "espressif,esp32-sdspi";
status = "disabled"; // Must be started after display
pin-cs = <&gpio0 21 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
display@1 {
compatible = "display-placeholder";
};
};
// ES8311

View File

@ -69,8 +69,9 @@
pin-miso = <&gpio0 39 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 40 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 12 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -55,8 +55,9 @@
pin-miso = <&gpio0 39 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 40 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 12 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -53,21 +53,21 @@
spi0 {
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
cs-gpios = <&gpio0 5 GPIO_FLAG_NONE>, // Display
<&gpio0 4 GPIO_FLAG_NONE>; // SD card
cs-gpios = <&gpio0 4 GPIO_FLAG_NONE>, // SD card
<&gpio0 5 GPIO_FLAG_NONE>; // Display
pin-mosi = <&gpio0 23 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 38 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 18 GPIO_FLAG_NONE>;
display@0 {
compatible = "display-placeholder";
};
sdcard@1 {
sdcard@0 {
compatible = "espressif,esp32-sdspi";
status = "disabled"; // Must be started after display
pin-cs = <&gpio0 4 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
display@1 {
compatible = "display-placeholder";
};
};
// NS4168: Speaker and microphone

View File

@ -78,21 +78,21 @@
spi0 {
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
cs-gpios = <&gpio0 3 GPIO_FLAG_NONE>, // Display
<&gpio0 4 GPIO_FLAG_NONE>; // SD card
cs-gpios = <&gpio0 4 GPIO_FLAG_NONE>, // SD card
<&gpio0 3 GPIO_FLAG_NONE>; // Display
pin-mosi = <&gpio0 37 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 35 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 36 GPIO_FLAG_NONE>;
display@0 {
compatible = "display-placeholder";
};
sdcard@1 {
sdcard@0 {
compatible = "espressif,esp32-sdspi";
status = "disabled"; // Must be started after display
pin-cs = <&gpio0 4 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
display@1 {
compatible = "display-placeholder";
};
};
// TODO: Enable speaker via ES7210 I2C: https://github.com/m5stack/M5Unified/blob/a6256725481f1bc366655fa48cf03b6095e30ad1/src/M5Unified.cpp#L417

View File

@ -49,8 +49,9 @@
pin-sclk = <&gpio0 39 GPIO_FLAG_NONE>;
max-transfer-size = <4096>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 47 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -112,20 +112,20 @@
spi0 {
compatible = "espressif,esp32-spi";
host = <SPI2_HOST>;
cs-gpios = <&gpio0 3 GPIO_FLAG_NONE>, // Display
<&gpio0 4 GPIO_FLAG_NONE>; // SD card
cs-gpios = <&gpio0 4 GPIO_FLAG_NONE>, // SD card
<&gpio0 3 GPIO_FLAG_NONE>; // Display
pin-mosi = <&gpio0 37 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 35 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 36 GPIO_FLAG_NONE>;
display@0 {
compatible = "display-placeholder";
sdcard@0 {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 4 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
sdcard@1 {
compatible = "espressif,esp32-sdspi";
status = "disabled"; // Must be started after display
frequency-khz = <20000>;
display@1 {
compatible = "display-placeholder";
};
};

View File

@ -71,8 +71,9 @@
pin-miso = <&gpio0 4 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 5 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 7 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -13,6 +13,7 @@
#include <bindings/ina226.h>
#include <bindings/pi4ioe5v6408.h>
#include <bindings/rx8130ce.h>
#include <tactility/bindings/esp32_sdspi.h>
/ {
compatible = "root";

View File

@ -1,7 +1,9 @@
#include "hal/SdlDisplay.h"
#include "hal/SdlKeyboard.h"
#include "hal/SimulatorPower.h"
#include "hal/SimulatorSdCard.h"
#include <src/lv_init.h> // LVGL
#include <Tactility/hal/Configuration.h>
#define TAG "hardware"
@ -13,6 +15,7 @@ static std::vector<std::shared_ptr<tt::hal::Device>> createDevices() {
std::make_shared<SdlDisplay>(),
std::make_shared<SdlKeyboard>(),
std::make_shared<SimulatorPower>(),
std::make_shared<SimulatorSdCard>()
};
}

View File

@ -0,0 +1,42 @@
#pragma once
#include "Tactility/hal/sdcard/SdCardDevice.h"
#include <Tactility/RecursiveMutex.h>
#include <memory>
using tt::hal::sdcard::SdCardDevice;
class SimulatorSdCard final : public SdCardDevice {
State state;
std::shared_ptr<tt::Lock> lock;
std::string mountPath;
public:
SimulatorSdCard() : SdCardDevice(MountBehaviour::AtBoot),
state(State::Unmounted),
lock(std::make_shared<tt::RecursiveMutex>())
{}
std::string getName() const override { return "Mock SD Card"; }
std::string getDescription() const override { return ""; }
bool mount(const std::string& newMountPath) override {
state = State::Mounted;
mountPath = newMountPath;
return true;
}
bool unmount() override {
state = State::Unmounted;
mountPath = "";
return true;
}
std::string getMountPath() const override { return mountPath; }
std::shared_ptr<tt::Lock> getLock() const override { return lock; }
State getState(TickType_t timeout) const override { return state; }
};

View File

@ -6,8 +6,6 @@
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/display_placeholder.h>
#include <tactility/bindings/touch_placeholder.h>
/ {
compatible = "root";
@ -51,6 +49,7 @@
sdcard@2 {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 43 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -56,8 +56,9 @@
pin-miso = <&gpio0 16 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 21 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 17 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -57,8 +57,9 @@
pin-miso = <&gpio0 15 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 17 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 18 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -6,7 +6,6 @@
#include <tactility/bindings/esp32_i2c.h>
#include <tactility/bindings/esp32_spi.h>
#include <tactility/bindings/esp32_sdspi.h>
#include <tactility/bindings/display_placeholder.h>
// Reference: https://www.waveshare.com/wiki/ESP32-S3-Touch-LCD-1.47
/ {
@ -45,13 +44,13 @@
spi1 {
compatible = "espressif,esp32-spi";
host = <SPI3_HOST>;
cs-gpios = <&gpio0 14 GPIO_FLAG_NONE>;
pin-mosi = <&gpio0 15 GPIO_FLAG_NONE>;
pin-miso = <&gpio0 17 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 16 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 14 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -37,8 +37,9 @@
pin-miso = <&gpio0 13 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 12 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 10 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -36,8 +36,9 @@
pin-miso = <&gpio0 38 GPIO_FLAG_NONE>;
pin-sclk = <&gpio0 39 GPIO_FLAG_NONE>;
sdcard@0 {
sdcard {
compatible = "espressif,esp32-sdspi";
pin-cs = <&gpio0 41 GPIO_FLAG_NONE>;
frequency-khz = <20000>;
};
};

View File

@ -27,18 +27,12 @@ bool Gt911Touch::createIoHandle(esp_lcd_panel_io_handle_t& outHandle) {
return false;
}
io_config.scl_speed_hz = esp32_i2c_master_get_clock_frequency(configuration->i2cController);
// Legacy I2C implementation
auto* driver = device_get_driver(i2c);
if (driver_is_compatible(driver, "espressif,esp32-i2c")) {
auto port = static_cast<const Esp32I2cConfig*>(i2c->config)->port;
return esp_lcd_new_panel_io_i2c_v1(port, &io_config, &outHandle) == ESP_OK;
}
// Target I2C implementation
if (driver_is_compatible(driver, "espressif,esp32-i2c-master")) {
auto* bus = esp32_i2c_master_get_bus_handle(i2c);
} else if (driver_is_compatible(driver, "espressif,esp32-i2c-master")) {
auto bus = esp32_i2c_master_get_bus_handle(i2c);
return esp_lcd_new_panel_io_i2c_v2(bus, &io_config, &outHandle) == ESP_OK;
}
@ -61,9 +55,9 @@ esp_lcd_touch_config_t Gt911Touch::createEspLcdTouchConfig() {
.interrupt = configuration->pinInterruptLevel,
},
.flags = {
.swap_xy = static_cast<unsigned int>(configuration->swapXy),
.mirror_x = static_cast<unsigned int>(configuration->mirrorX),
.mirror_y = static_cast<unsigned int>(configuration->mirrorY),
.swap_xy = configuration->swapXy,
.mirror_x = configuration->mirrorX,
.mirror_y = configuration->mirrorY,
},
.process_coordinates = nullptr,
.interrupt_callback = nullptr,

View File

@ -8,11 +8,11 @@ properties:
required: true
description: "One of enum Esp32GroveMode"
pinSdaTx:
type: phandles
type: phandle-array
required: true
description: SDA (I2C) or TX (UART) pin
pinSclRx:
type: phandles
type: phandle-array
required: true
description: SCL (I2C) or RX (UART) pin
uartPort:

View File

@ -22,8 +22,8 @@ properties:
Clock source for the I2C peripheral.
If not specified, a default clock source will be used.
pin-sda:
type: phandles
type: phandle-array
required: true
pin-scl:
type: phandles
type: phandle-array
required: true

View File

@ -16,8 +16,8 @@ properties:
required: true
description: Initial clock frequency in Hz
pin-sda:
type: phandles
type: phandle-array
required: true
pin-scl:
type: phandles
type: phandle-array
required: true

View File

@ -12,22 +12,22 @@ properties:
The port number, defined by i2s_port_t.
Depending on the hardware, these values are available: I2S_NUM_0, I2S_NUM_1
pin-bclk:
type: phandles
type: phandle-array
required: true
description: Bit clock pin
pin-ws:
type: phandles
type: phandle-array
required: true
description: Word (slot) select pin
pin-data-out:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
description: Data output pin
pin-data-in:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
description: Data input pin
pin-mclk:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
description: Master clock pin

View File

@ -4,40 +4,40 @@ compatible: "espressif,esp32-sdmmc"
properties:
pin-clk:
type: phandles
type: phandle-array
required: true
pin-cmd:
type: phandles
type: phandle-array
required: true
pin-d0:
type: phandles
type: phandle-array
required: true
pin-d1:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
pin-d2:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
pin-d3:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
pin-d4:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
pin-d5:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
pin-d6:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
pin-d7:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
pin-cd:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
pin-wp:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
bus-width:
type: int

View File

@ -5,16 +5,20 @@ compatible: "espressif,esp32-sdspi"
bus: spi
properties:
pin-cs:
type: phandle-array
required: true
description: Chip select GPIO
pin-cd:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
description: Card detect GPIO
pin-wp:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
description: Write protect GPIO
pin-int:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
description: Interrupt GPIO
frequency-khz:

View File

@ -12,22 +12,22 @@ properties:
The SPI host (controller) to use.
Defined by spi_host_device_t (e.g. SPI2_HOST, SPI3_HOST).
pin-sclk:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
pin-mosi:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
description: MOSI (Data 0) pin
pin-miso:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
description: MISO (Data 1) pin
pin-wp:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
description: WP (Data 2) pin
pin-hd:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
description: HD (Data 3) pin
max-transfer-size:
@ -38,6 +38,5 @@ properties:
0 means the platform decides the limit.
cs-gpios:
type: phandle-array
element-type: "struct GpioPinSpec"
default: "{ }"
default: { 0 }
description: Null-terminated array of chip select GPIO pin specs for peripherals on this bus

View File

@ -12,18 +12,18 @@ properties:
The port number, defined by uart_port_t.
Depending on the hardware, these values are available: UART_NUM_0, UART_NUM_1, UART_NUM_2
pin-tx:
type: phandles
type: phandle-array
required: true
description: TX pin
pin-rx:
type: phandles
type: phandle-array
required: true
description: RX pin
pin-cts:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
description: CTS pin
pin-rts:
type: phandles
type: phandle-array
default: GPIO_PIN_SPEC_NONE
description: RTS pin

View File

@ -9,6 +9,7 @@ extern "C" {
#endif
struct Esp32SdspiConfig {
struct GpioPinSpec pin_cs;
struct GpioPinSpec pin_cd;
struct GpioPinSpec pin_wp;
struct GpioPinSpec pin_int;

View File

@ -23,29 +23,10 @@ struct Esp32SpiConfig {
struct GpioPinSpec pin_hd;
/** Data transfer size limit in bytes. 0 means the platform decides the limit. */
int max_transfer_size;
/** Array of chip select GPIO pin specs */
struct GpioPinSpec* cs_gpios;
/** The item count of cs_gpios */
uint8_t cs_gpios_count;
/** Null-terminated array of chip select GPIO pin specs */
struct GpioPinSpec cs_gpios[];
};
/**
* @brief Get the CS pin spec for a child device on this SPI bus.
* Uses the child device's address as index into the parent's cs_gpios array.
* @param[in] child_device a child device of an SPI controller
* @param[out] out_pin the GPIO pin spec for the CS pin
* @retval ERROR_NONE on success
* @retval ERROR_INVALID_STATE if the parent is not an SPI controller
* @retval ERROR_OUT_OF_RANGE if the device address exceeds the cs_gpios array
*/
error_t esp32_spi_get_cs_pin(struct Device* child_device, struct GpioPinSpec* out_pin);
/**
* @brief Drive all CS pins on this SPI bus high (deselected).
* @param[in] device the SPI controller device
*/
void esp32_spi_deselect_all_cs(struct Device* device);
#ifdef __cplusplus
}
#endif

View File

@ -11,7 +11,7 @@ extern "C" {
struct Esp32SdspiConfig;
typedef void* Esp32SdspiHandle;
Esp32SdspiHandle esp32_sdspi_fs_alloc(const struct Esp32SdspiConfig* config, int spi_host, int cs_pin, const char* mount_path);
Esp32SdspiHandle esp32_sdspi_fs_alloc(const struct Esp32SdspiConfig* config, int spi_host, const char* mount_path);
void esp32_sdspi_fs_free(Esp32SdspiHandle handle);
sdmmc_card_t* esp32_sdspi_fs_get_card(Esp32SdspiHandle handle);

View File

@ -1000,7 +1000,7 @@ const BluetoothApi nimble_bluetooth_api = {
static void create_child_device(struct Device* parent, const char* name,
Driver* drv, struct Device*& out) {
out = new Device { .address = 0, .name = name, .config = nullptr, .parent = nullptr, .internal = nullptr };
out = new Device { .name = name, .config = nullptr, .parent = nullptr, .internal = nullptr };
device_construct(out);
device_set_parent(out, parent);
device_set_driver(out, drv);

View File

@ -238,8 +238,7 @@ static constexpr I2cControllerApi ESP32_I2C_API = {
.write = write,
.write_read = write_read,
.read_register = read_register,
.write_register = write_register,
.probe = nullptr
.write_register = write_register
};
extern Module platform_esp32_module;

View File

@ -10,7 +10,6 @@
#include <tactility/drivers/esp32_sdmmc.h>
#include <tactility/drivers/esp32_sdmmc_fs.h>
#include <tactility/drivers/gpio_descriptor.h>
#include <tactility/drivers/sdcard.h>
#include <tactility/filesystem/file_system.h>
#include <tactility/log.h>
@ -178,7 +177,7 @@ Driver esp32_sdmmc_driver = {
.start_device = start,
.stop_device = stop,
.api = nullptr,
.device_type = &SDCARD_TYPE,
.device_type = nullptr,
.owner = &platform_esp32_module,
.internal = nullptr
};

View File

@ -10,7 +10,6 @@
#include <tactility/drivers/esp32_spi.h>
#include <tactility/drivers/gpio_descriptor.h>
#include <tactility/drivers/spi_controller.h>
#include <tactility/drivers/sdcard.h>
#include <tactility/filesystem/file_system.h>
#include <tactility/log.h>
@ -25,6 +24,7 @@ struct Esp32SdspiInternal {
RecursiveMutex mutex = {};
Esp32SdspiHandle fs_handle = nullptr;
FileSystem* file_system = nullptr;
GpioDescriptor* pin_cs_descriptor = nullptr;
GpioDescriptor* pin_cd_descriptor = nullptr;
GpioDescriptor* pin_wp_descriptor = nullptr;
GpioDescriptor* pin_int_descriptor = nullptr;
@ -40,6 +40,7 @@ struct Esp32SdspiInternal {
}
void cleanup_pins() {
release_pin(&pin_cs_descriptor);
release_pin(&pin_cd_descriptor);
release_pin(&pin_wp_descriptor);
release_pin(&pin_int_descriptor);
@ -67,6 +68,7 @@ static error_t start(Device* device) {
auto* config = GET_CONFIG(device);
bool pins_ok =
acquire_pin_or_set_null(config->pin_cs, &data->pin_cs_descriptor) &&
acquire_pin_or_set_null(config->pin_cd, &data->pin_cd_descriptor) &&
acquire_pin_or_set_null(config->pin_wp, &data->pin_wp_descriptor) &&
acquire_pin_or_set_null(config->pin_int, &data->pin_int_descriptor);
@ -80,25 +82,8 @@ static error_t start(Device* device) {
return ERROR_RESOURCE;
}
GpioPinSpec cs_pin_spec;
if (esp32_spi_get_cs_pin(device, &cs_pin_spec) != ERROR_NONE) {
LOG_E(TAG, "Failed to get CS pin from parent SPI controller");
data->cleanup_pins();
device_set_driver_data(device, nullptr);
data->unlock();
delete data;
return ERROR_RESOURCE;
}
auto* spi_config = static_cast<const Esp32SpiConfig*>(parent->config);
// Lower all CS pins
esp32_spi_deselect_all_cs(parent);
// Manually set the CS pin fo
gpio_set_direction(static_cast<gpio_num_t>(cs_pin_spec.pin), GPIO_MODE_OUTPUT);
gpio_set_level(static_cast<gpio_num_t>(cs_pin_spec.pin), 255);
data->fs_handle = esp32_sdspi_fs_alloc(config, spi_config->host, cs_pin_spec.pin, "/sdcard");
data->fs_handle = esp32_sdspi_fs_alloc(config, spi_config->host, "/sdcard");
if (!data->fs_handle) {
data->cleanup_pins();
device_set_driver_data(device, nullptr);
@ -166,7 +151,7 @@ Driver esp32_sdspi_driver = {
.start_device = start,
.stop_device = stop,
.api = nullptr,
.device_type = &SDCARD_TYPE,
.device_type = nullptr,
.owner = &platform_esp32_module,
.internal = nullptr
};

View File

@ -17,14 +17,12 @@ struct Esp32SdspiFsData {
const std::string mount_path;
const Esp32SdspiConfig* config;
int spi_host;
int cs_pin;
sdmmc_card_t* card;
Esp32SdspiFsData(const Esp32SdspiConfig* config, int spi_host, int cs_pin, const std::string& mount_path) :
Esp32SdspiFsData(const Esp32SdspiConfig* config, int spi_host, const std::string& mount_path) :
mount_path(mount_path),
config(config),
spi_host(spi_host),
cs_pin(cs_pin),
card(nullptr)
{}
};
@ -36,8 +34,8 @@ static gpio_num_t to_native_pin(GpioPinSpec pin_spec) {
extern "C" {
Esp32SdspiHandle esp32_sdspi_fs_alloc(const Esp32SdspiConfig* config, int spi_host, int cs_pin, const char* mount_path) {
return new(std::nothrow) Esp32SdspiFsData(config, spi_host, cs_pin, mount_path);
Esp32SdspiHandle esp32_sdspi_fs_alloc(const Esp32SdspiConfig* config, int spi_host, const char* mount_path) {
return new(std::nothrow) Esp32SdspiFsData(config, spi_host, mount_path);
}
void esp32_sdspi_fs_free(Esp32SdspiHandle handle) {
@ -64,7 +62,7 @@ static error_t mount(void* data) {
sdspi_device_config_t slot_config = SDSPI_DEVICE_CONFIG_DEFAULT();
slot_config.host_id = static_cast<spi_host_device_t>(fs_data->spi_host);
slot_config.gpio_cs = static_cast<gpio_num_t>(fs_data->cs_pin);
slot_config.gpio_cs = to_native_pin(config->pin_cs);
slot_config.gpio_cd = to_native_pin(config->pin_cd);
slot_config.gpio_wp = to_native_pin(config->pin_wp);
slot_config.gpio_int = to_native_pin(config->pin_int);

View File

@ -10,7 +10,6 @@
#include <cstring>
#include <new>
#include <soc/gpio_num.h>
#include <vector>
#define TAG "esp32_spi"
@ -23,16 +22,13 @@ struct Esp32SpiInternal {
RecursiveMutex mutex = {};
bool initialized = false;
// Bus pin descriptors
// Pin descriptors
GpioDescriptor* sclk_descriptor = nullptr;
GpioDescriptor* mosi_descriptor = nullptr;
GpioDescriptor* miso_descriptor = nullptr;
GpioDescriptor* wp_descriptor = nullptr;
GpioDescriptor* hd_descriptor = nullptr;
// CS pin descriptors
std::vector<GpioDescriptor*> cs_descriptors;
explicit Esp32SpiInternal() {
recursive_mutex_construct(&mutex);
}
@ -48,10 +44,6 @@ struct Esp32SpiInternal {
release_pin(&miso_descriptor);
release_pin(&wp_descriptor);
release_pin(&hd_descriptor);
for (auto*& desc : cs_descriptors) {
release_pin(&desc);
}
cs_descriptors.clear();
}
};
@ -126,30 +118,22 @@ static error_t start(Device* device) {
return ERROR_RESOURCE;
}
// Acquire and deselect all CS pins (drive high)
for (uint8_t i = 0; i < dts_config->cs_gpios_count; i++) {
const GpioPinSpec* cs = &dts_config->cs_gpios[i];
if (cs->gpio_controller == nullptr) continue;
// Deselect all CS pins (drive high) before any SPI communication
const GpioPinSpec* cs = dts_config->cs_gpios;
while (cs->gpio_controller != nullptr) {
GpioDescriptor* desc = gpio_descriptor_acquire(cs->gpio_controller, cs->pin, GPIO_OWNER_SPI);
if (desc != nullptr) {
gpio_descriptor_set_flags(desc, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_level(desc, true);
data->cs_descriptors.push_back(desc);
gpio_descriptor_release(desc);
}
cs++;
}
data->initialized = true;
return ERROR_NONE;
}
void esp32_spi_deselect_all_cs(Device* device) {
auto* data = GET_DATA(device);
if (data == nullptr) return;
for (auto* desc : data->cs_descriptors) {
gpio_descriptor_set_level(desc, true);
}
}
static error_t stop(Device* device) {
LOG_I(TAG, "stop %s", device->name);
auto* driver_data = GET_DATA(device);
@ -165,16 +149,6 @@ static error_t stop(Device* device) {
return ERROR_NONE;
}
error_t esp32_spi_get_cs_pin(Device* child_device, GpioPinSpec* out_pin) {
auto* parent = device_get_parent(child_device);
if (parent == nullptr || device_get_type(parent) != &SPI_CONTROLLER_TYPE) return ERROR_INVALID_STATE;
auto* config = GET_CONFIG(parent);
int32_t index = child_device->address;
if (index < 0 || index >= config->cs_gpios_count) return ERROR_OUT_OF_RANGE;
*out_pin = config->cs_gpios[index];
return ERROR_NONE;
}
const static struct SpiControllerApi esp32_spi_api = {
.lock = lock,
.try_lock = try_lock,

View File

@ -0,0 +1,84 @@
#pragma once
#include <tactility/hal/Device.h>
#include <Tactility/Lock.h>
#include <Tactility/TactilityCore.h>
struct FileSystem;
namespace tt::hal::sdcard {
/**
* Warning: getLock() does not have to be used when calling any of the functions of this class.
* The lock is only used for file access on the path where the SD card is mounted.
* This is mainly used when accessing the SD card on a shared SPI bus.
*/
class SdCardDevice : public Device {
public:
enum class State {
Mounted,
Unmounted,
Error,
Timeout // Failed to retrieve state due to timeout
};
enum class MountBehaviour {
AtBoot, /** Only mount at boot */
Anytime /** Mount/dismount any time */
};
private:
MountBehaviour mountBehaviour;
FileSystem* fileSystem;
public:
explicit SdCardDevice(MountBehaviour mountBehaviour);
~SdCardDevice() override;
Type getType() const final { return Type::SdCard; };
/**
* Mount the device.
* @param mountPath the path to mount at
* @return true on successful mount
*/
virtual bool mount(const std::string& mountPath) = 0;
/**
* Unmount the device.
* @return true on successful unmount
*/
virtual bool unmount() = 0;
virtual State getState(TickType_t timeout = kernel::MAX_TICKS) const = 0;
/** @return empty string when not mounted or the mount path if mounted */
virtual std::string getMountPath() const = 0;
/** @return non-null lock, used by code that wants to access files on the mount path of this SD card */
virtual std::shared_ptr<Lock> getLock() const = 0;
/** @return the MountBehaviour of this device */
virtual MountBehaviour getMountBehaviour() const { return mountBehaviour; }
/** @return true if the SD card was mounted, returns false when it was not or when a timeout happened. */
bool isMounted(TickType_t timeout = kernel::MAX_TICKS) const { return getState(timeout) == State::Mounted; }
};
/** Return the SdCard device if the path is within the SdCard mounted path (path std::string::starts_with() check), otherwise return nullptr */
std::shared_ptr<SdCardDevice> find(const std::string& path);
/**
* Attempt to find an SD card that the specified belongs to,
* and returns its lock if the SD card is mounted. Otherwise it returns nullptr.
* @param[in] a path on a file system (e.g. file, directory, etc.)
* @return the lock of a mounted SD card or otherwise null
*/
std::shared_ptr<Lock> findSdCardLock(const std::string& path);
} // namespace tt::hal

View File

@ -1,20 +0,0 @@
#pragma once
#include <memory.h>
#include <string.h>
#include <Tactility/Lock.h>
namespace tt::hal::sdcard {
/**
* Attempt to find an SD card that the specified belongs to,
* and returns its lock if the SD card is mounted. Otherwise it returns nullptr.
* @param[in] a path on a file system (e.g. file, directory, etc.)
* @return the lock of a mounted SD card or otherwise null
*/
std::shared_ptr<Lock> findSdCardLock(const std::string& path);
void mountAll();
}

View File

@ -0,0 +1,7 @@
#pragma once
namespace tt::hal::sdcard {
void mountAll();
}

View File

@ -2,6 +2,7 @@
#include <Tactility/file/File.h>
#include <Tactility/file/FileLock.h>
#include <Tactility/hal/sdcard/SdCardDevice.h>
#include <Tactility/Logger.h>
#include <Tactility/LogMessages.h>
#include <Tactility/MountPoints.h>

View File

@ -1,6 +1,7 @@
#include "Tactility/app/fileselection/State.h"
#include <Tactility/file/File.h>
#include "Tactility/hal/sdcard/SdCardDevice.h"
#include <Tactility/Logger.h>
#include <Tactility/MountPoints.h>
#include <Tactility/kernel/Platform.h>

View File

@ -1,6 +1,7 @@
#include "Tactility/file/FileLock.h"
#include <Tactility/hal/SdCard.h>
#include <Tactility/hal/sdcard/SdCardDevice.h>
#include <Tactility/Mutex.h>
namespace tt::file {

View File

@ -5,7 +5,7 @@
#include <tactility/hal/Device.h>
#include <Tactility/hal/display/DisplayDevice.h>
#include <Tactility/hal/SdCard.h>
#include <Tactility/hal/sdcard/SdCardMounting.h>
#include <Tactility/hal/touch/TouchDevice.h>
#include <Tactility/kernel/SystemEvents.h>

View File

@ -1,11 +1,12 @@
#include "Tactility/hal/sdcard/SdCardDevice.h"
#include <Tactility/lvgl/LvglSync.h>
#include <tactility/device.h>
#include <tactility/drivers/sdcard.h>
#include <tactility/filesystem/file_system.h>
#include <cstring>
#include <string>
#include <memory>
namespace tt::hal::sdcard {
@ -37,14 +38,4 @@ std::shared_ptr<Lock> findSdCardLock(const std::string& path) {
return ctx.result;
}
void mountAll() {
device_for_each_of_type(&SDCARD_TYPE, nullptr, [](::Device* device, void*) -> bool {
if (!device_is_ready(device)) {
if (device_start(device) != ERROR_NONE) {
}
}
return true;
});
}
}

View File

@ -0,0 +1,52 @@
#include <Tactility/hal/sdcard/SdCardDevice.h>
#include <tactility/filesystem/file_system.h>
#include <cstring>
namespace tt::hal::sdcard {
static error_t mount(void* data) {
auto* device = static_cast<SdCardDevice*>(data);
auto path = device->getMountPath();
if (!device->mount(path)) return ERROR_UNDEFINED;
return ERROR_NONE;
}
static error_t unmount(void* data) {
auto* device = static_cast<SdCardDevice*>(data);
if (!device->unmount()) return ERROR_UNDEFINED;
return ERROR_NONE;
}
static bool is_mounted(void* data) {
auto* device = static_cast<SdCardDevice*>(data);
return device->isMounted();
}
static error_t get_path(void* data, char* out_path, size_t out_path_size) {
auto* device = static_cast<SdCardDevice*>(data);
const auto mount_path = device->getMountPath();
if (mount_path.size() >= out_path_size) return ERROR_BUFFER_OVERFLOW;
if (mount_path.empty()) return ERROR_INVALID_STATE;
strncpy(out_path, mount_path.c_str(), out_path_size);
return ERROR_NONE;
}
FileSystemApi sdCardDeviceApi = {
.mount = mount,
.unmount = unmount,
.is_mounted = is_mounted,
.get_path = get_path
};
SdCardDevice::SdCardDevice(MountBehaviour mountBehaviour) : mountBehaviour(mountBehaviour) {
fileSystem = file_system_add(&sdCardDeviceApi, this);
check(fileSystem != nullptr);
}
SdCardDevice::~SdCardDevice() {
file_system_remove(fileSystem);
}
}

View File

@ -0,0 +1,36 @@
#include <Tactility/hal/sdcard/SdCardMounting.h>
#include <Tactility/hal/sdcard/SdCardDevice.h>
#include <Tactility/Logger.h>
#include <format>
namespace tt::hal::sdcard {
static const auto LOGGER = Logger("SdCardMounting");
constexpr auto* TT_SDCARD_MOUNT_POINT = "/sdcard";
static void mount(const std::shared_ptr<SdCardDevice>& sdcard, const std::string& path) {
LOGGER.info("Mounting sdcard at {}", path);
if (!sdcard->mount(path)) {
LOGGER.warn("SD card mount failed for {} (init can continue)", path);
}
}
static std::string getMountPath(int index, int count) {
return (count == 1) ? TT_SDCARD_MOUNT_POINT : std::format("{}{}", TT_SDCARD_MOUNT_POINT, index);
}
void mountAll() {
const auto sdcards = hal::findDevices<SdCardDevice>(Device::Type::SdCard);
// Numbered mount path name
for (int i = 0; i < sdcards.size(); i++) {
auto sdcard = sdcards[i];
if (!sdcard->isMounted() && sdcard->getMountBehaviour() == SdCardDevice::MountBehaviour::AtBoot) {
std::string mount_path = getMountPath(i, sdcards.size());
mount(sdcard, mount_path);
}
}
}
}

View File

@ -16,6 +16,7 @@
#include <Tactility/app/AppRegistration.h>
#include <Tactility/app/AppManifest.h>
#include <Tactility/app/App.h>
#include <Tactility/hal/sdcard/SdCardDevice.h>
#include <Tactility/service/wifi/Wifi.h>
#include <esp_wifi_default.h>
#include <Tactility/network/HttpdReq.h>

View File

@ -8,6 +8,7 @@
#include <Tactility/Paths.h>
#include <Tactility/Tactility.h>
#include <Tactility/hal/sdcard/SdCardDevice.h>
#include <dirent.h>
#include <format>
#include <map>

View File

@ -1,6 +1,7 @@
#include <Tactility/MountPoints.h>
#include <Tactility/file/File.h>
#include <Tactility/file/PropertiesFile.h>
#include <Tactility/hal/sdcard/SdCardDevice.h>
#include <Tactility/Logger.h>
#include <Tactility/settings/BootSettings.h>

View File

@ -1,5 +1,9 @@
description: SPI peripheral
description: SPI peripheral with chip select
compatible: "spi-peripheral"
properties: {}
properties:
pin-cs:
type: phandle-array
required: true
description: Chip select GPIO

View File

@ -1,14 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include <tactility/device.h>
extern const struct DeviceType SDCARD_TYPE;
#ifdef __cplusplus
}
#endif

View File

@ -1,17 +1,23 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include <stdint.h>
#include <tactility/device.h>
#include <tactility/drivers/gpio.h>
#ifdef __cplusplus
extern "C" {
#endif
struct SpiPeripheralConfig {
uint8_t _unused;
struct GpioPinSpec pin_cs;
};
struct SpiPeripheralApi {
struct GpioDescriptor* (*get_cs_descriptor)(struct Device* device);
};
struct GpioDescriptor* spi_peripheral_get_cs_descriptor(struct Device* device);
extern const struct DeviceType SPI_PERIPHERAL_TYPE;
#ifdef __cplusplus

View File

@ -24,7 +24,6 @@ typedef int error_t;
#define ERROR_NOT_SUPPORTED 10
#define ERROR_NOT_ALLOWED 11
#define ERROR_BUFFER_OVERFLOW 12
#define ERROR_OUT_OF_RANGE 13
/** Convert an error_t to a human-readable text. Useful for logging. */
const char* error_to_string(error_t error);

View File

@ -1,10 +0,0 @@
// SPDX-License-Identifier: Apache-2.0
#include <tactility/drivers/sdcard.h>
extern "C" {
const struct DeviceType SDCARD_TYPE {
.name = "sdcard"
};
}

View File

@ -1,12 +1,61 @@
// SPDX-License-Identifier: Apache-2.0
#include <tactility/drivers/spi_peripheral.h>
#include <tactility/drivers/gpio_controller.h>
#include <tactility/drivers/spi_controller.h>
#include <tactility/driver.h>
#include <tactility/module.h>
#include <tactility/log.h>
#define TAG "spi_peripheral"
#define GET_CONFIG(device) ((const struct SpiPeripheralConfig*)device->config)
extern "C" {
static error_t start(Device*) { return ERROR_NONE; }
static error_t stop(Device*) { return ERROR_NONE; }
static error_t start(Device* device) {
auto* parent = device_get_parent(device);
if (parent == nullptr || device_get_type(parent) != &SPI_CONTROLLER_TYPE) {
LOG_E(TAG, "Parent is not an SPI controller");
return ERROR_INVALID_STATE;
}
auto* config = GET_CONFIG(device);
GpioDescriptor* cs = nullptr;
if (config->pin_cs.gpio_controller != nullptr) {
cs = gpio_descriptor_acquire(config->pin_cs.gpio_controller, config->pin_cs.pin, GPIO_OWNER_SPI);
if (cs == nullptr) {
LOG_E(TAG, "Failed to acquire CS pin");
return ERROR_RESOURCE;
}
gpio_descriptor_set_flags(cs, GPIO_FLAG_DIRECTION_OUTPUT);
gpio_descriptor_set_level(cs, true);
}
device_set_driver_data(device, cs);
return ERROR_NONE;
}
static error_t stop(Device* device) {
auto* cs = static_cast<GpioDescriptor*>(device_get_driver_data(device));
if (cs != nullptr) {
gpio_descriptor_release(cs);
}
device_set_driver_data(device, nullptr);
return ERROR_NONE;
}
static GpioDescriptor* get_cs_descriptor(Device* device) {
return static_cast<GpioDescriptor*>(device_get_driver_data(device));
}
static const SpiPeripheralApi spi_peripheral_api = {
.get_cs_descriptor = get_cs_descriptor
};
GpioDescriptor* spi_peripheral_get_cs_descriptor(Device* device) {
auto* driver = device_get_driver(device);
return ((const SpiPeripheralApi*)driver->api)->get_cs_descriptor(device);
}
const DeviceType SPI_PERIPHERAL_TYPE = {
.name = "spi_peripheral"
@ -19,7 +68,7 @@ Driver spi_peripheral_driver = {
.compatible = (const char*[]) { "spi-peripheral", nullptr },
.start_device = start,
.stop_device = stop,
.api = nullptr,
.api = &spi_peripheral_api,
.device_type = &SPI_PERIPHERAL_TYPE,
.owner = &root_module,
.internal = nullptr