Tactility.py 3.0.0 and SDK updates for 0.7.0-dev (#19)
- Remove `Libraries/Str` - Replaced usage of `TactilityC` FreeRtos features with `TactilityFreeRtos` library - Update `tactility.py` - Removed redundant code from `TactilityCpp`
This commit is contained in:
committed by
GitHub
parent
3bc1e7a373
commit
b6c27b64d4
@@ -1,15 +1,11 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES
|
file(GLOB_RECURSE SOURCE_FILES
|
||||||
Source/*.c*
|
Source/*.c*
|
||||||
# Library source files must be included directly,
|
|
||||||
# because all regular dependencies get stripped by elf_loader's cmake script
|
|
||||||
../../../Libraries/Str/Source/*.c**
|
|
||||||
)
|
)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
# Library headers must be included directly,
|
# Library headers must be included directly,
|
||||||
# because all regular dependencies get stripped by elf_loader's cmake script
|
# because all regular dependencies get stripped by elf_loader's cmake script
|
||||||
INCLUDE_DIRS ../../../Libraries/Str/Include
|
|
||||||
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
|
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
|
||||||
REQUIRES TactilitySDK
|
REQUIRES TactilitySDK
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <tt_lvgl_toolbar.h>
|
#include <tt_lvgl_toolbar.h>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
constexpr auto* TAG = "Calculator";
|
constexpr auto* TAG = "Calculator";
|
||||||
|
|
||||||
@@ -45,10 +46,10 @@ void Calculator::handleInput(const char* txt) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::deque<Str> Calculator::infixToRPN(const Str& infix) {
|
std::deque<std::string> Calculator::infixToRPN(const std::string& infix) {
|
||||||
std::stack<char> opStack;
|
std::stack<char> opStack;
|
||||||
std::deque<Str> output;
|
std::deque<std::string> output;
|
||||||
Str token;
|
std::string token;
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
|
|
||||||
while (i < infix.length()) {
|
while (i < infix.length()) {
|
||||||
@@ -56,20 +57,20 @@ std::deque<Str> Calculator::infixToRPN(const Str& infix) {
|
|||||||
|
|
||||||
if (isdigit(ch)) {
|
if (isdigit(ch)) {
|
||||||
token.clear();
|
token.clear();
|
||||||
while (i < infix.length() && (isdigit(infix[i]) || infix[i] == '.')) { token.append(infix[i++]); }
|
while (i < infix.length() && (isdigit(infix[i]) || infix[i] == '.')) { token += infix[i++]; }
|
||||||
output.push_back(token);
|
output.push_back(token);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ch == '(') { opStack.push(ch); } else if (ch == ')') {
|
if (ch == '(') { opStack.push(ch); } else if (ch == ')') {
|
||||||
while (!opStack.empty() && opStack.top() != '(') {
|
while (!opStack.empty() && opStack.top() != '(') {
|
||||||
output.push_back(Str(1, opStack.top()));
|
output.push_back(std::string(1, opStack.top()));
|
||||||
opStack.pop();
|
opStack.pop();
|
||||||
}
|
}
|
||||||
opStack.pop();
|
opStack.pop();
|
||||||
} else if (strchr("+-*/", ch)) {
|
} else if (strchr("+-*/", ch)) {
|
||||||
while (!opStack.empty() && precedence(opStack.top()) >= precedence(ch)) {
|
while (!opStack.empty() && precedence(opStack.top()) >= precedence(ch)) {
|
||||||
output.push_back(Str(1, opStack.top()));
|
output.push_back(std::string(1, opStack.top()));
|
||||||
opStack.pop();
|
opStack.pop();
|
||||||
}
|
}
|
||||||
opStack.push(ch);
|
opStack.push(ch);
|
||||||
@@ -79,18 +80,18 @@ std::deque<Str> Calculator::infixToRPN(const Str& infix) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (!opStack.empty()) {
|
while (!opStack.empty()) {
|
||||||
output.push_back(Str(1, opStack.top()));
|
output.push_back(std::string(1, opStack.top()));
|
||||||
opStack.pop();
|
opStack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
double Calculator::evaluateRPN(std::deque<Str> rpnQueue) {
|
double Calculator::evaluateRPN(std::deque<std::string> rpnQueue) {
|
||||||
std::stack<double> values;
|
std::stack<double> values;
|
||||||
|
|
||||||
while (!rpnQueue.empty()) {
|
while (!rpnQueue.empty()) {
|
||||||
Str token = rpnQueue.front();
|
std::string token = rpnQueue.front();
|
||||||
rpnQueue.pop_front();
|
rpnQueue.pop_front();
|
||||||
|
|
||||||
if (isdigit(token[0])) {
|
if (isdigit(token[0])) {
|
||||||
@@ -132,7 +133,7 @@ void Calculator::evaluateExpression() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double Calculator::computeFormula() {
|
double Calculator::computeFormula() {
|
||||||
return evaluateRPN(infixToRPN(Str(formulaBuffer)));
|
return evaluateRPN(infixToRPN(std::string(formulaBuffer)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Calculator::resetCalculator() {
|
void Calculator::resetCalculator() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <Str.h>
|
#include <string>
|
||||||
#include <TactilityCpp/App.h>
|
#include <TactilityCpp/App.h>
|
||||||
|
|
||||||
class Calculator final : public App {
|
class Calculator final : public App {
|
||||||
@@ -18,8 +18,8 @@ class Calculator final : public App {
|
|||||||
void handleInput(const char* txt);
|
void handleInput(const char* txt);
|
||||||
void evaluateExpression();
|
void evaluateExpression();
|
||||||
double computeFormula();
|
double computeFormula();
|
||||||
static std::deque<Str> infixToRPN(const Str& infix);
|
static std::deque<std::string> infixToRPN(const std::string& infix);
|
||||||
static double evaluateRPN(std::deque<Str> rpnQueue);
|
static double evaluateRPN(std::deque<std::string> rpnQueue);
|
||||||
void resetCalculator();
|
void resetCalculator();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
[manifest]
|
[manifest]
|
||||||
version=0.1
|
version=0.1
|
||||||
[target]
|
[target]
|
||||||
sdk=0.6.0
|
sdk=0.7.0-dev
|
||||||
platforms=esp32,esp32s3
|
platforms=esp32,esp32s3,esp32c6,esp32p4
|
||||||
[app]
|
[app]
|
||||||
id=one.tactility.calculator
|
id=one.tactility.calculator
|
||||||
versionName=0.2.0
|
versionName=0.3.0
|
||||||
versionCode=2
|
versionCode=3
|
||||||
name=Calculator
|
name=Calculator
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import requests
|
|||||||
import tarfile
|
import tarfile
|
||||||
|
|
||||||
ttbuild_path = ".tactility"
|
ttbuild_path = ".tactility"
|
||||||
ttbuild_version = "2.5.0"
|
ttbuild_version = "3.1.0"
|
||||||
ttbuild_cdn = "https://cdn.tactility.one"
|
ttbuild_cdn = "https://cdn.tactility.one"
|
||||||
ttbuild_sdk_json_validity = 3600 # seconds
|
ttbuild_sdk_json_validity = 3600 # seconds
|
||||||
ttport = 6666
|
ttport = 6666
|
||||||
@@ -20,20 +20,12 @@ verbose = False
|
|||||||
use_local_sdk = False
|
use_local_sdk = False
|
||||||
local_base_path = None
|
local_base_path = None
|
||||||
|
|
||||||
if sys.platform == "win32":
|
shell_color_red = "\033[91m"
|
||||||
shell_color_red = "\033[91m"
|
shell_color_orange = "\033[93m"
|
||||||
shell_color_orange = "\033[93m"
|
shell_color_green = "\033[32m"
|
||||||
shell_color_green = "\033[32m"
|
shell_color_purple = "\033[35m"
|
||||||
shell_color_purple = "\033[35m"
|
shell_color_cyan = "\033[36m"
|
||||||
shell_color_cyan = "\033[36m"
|
shell_color_reset = "\033[m"
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
else:
|
|
||||||
shell_color_red = "\033[91m"
|
|
||||||
shell_color_orange = "\033[93m"
|
|
||||||
shell_color_green = "\033[32m"
|
|
||||||
shell_color_purple = "\033[35m"
|
|
||||||
shell_color_cyan = "\033[36m"
|
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
|
|
||||||
def print_help():
|
def print_help():
|
||||||
print("Usage: python tactility.py [action] [options]")
|
print("Usage: python tactility.py [action] [options]")
|
||||||
@@ -115,9 +107,9 @@ def read_properties_file(path):
|
|||||||
#region SDK helpers
|
#region SDK helpers
|
||||||
|
|
||||||
def read_sdk_json():
|
def read_sdk_json():
|
||||||
json_file_path = os.path.join(ttbuild_path, "sdk.json")
|
json_file_path = os.path.join(ttbuild_path, "tool.json")
|
||||||
json_file = open(json_file_path)
|
with open(json_file_path) as json_file:
|
||||||
return json.load(json_file)
|
return json.load(json_file)
|
||||||
|
|
||||||
def get_sdk_dir(version, platform):
|
def get_sdk_dir(version, platform):
|
||||||
global use_local_sdk, local_base_path
|
global use_local_sdk, local_base_path
|
||||||
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
|
|||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
||||||
|
|
||||||
def get_sdk_url(version, platform):
|
def get_sdk_url(version, file):
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
|
return f"{ttbuild_cdn}/sdk/{version}/{file}"
|
||||||
|
|
||||||
def sdk_exists(version, platform):
|
def sdk_exists(version, platform):
|
||||||
sdk_dir = get_sdk_dir(version, platform)
|
sdk_dir = get_sdk_dir(version, platform)
|
||||||
return os.path.isdir(sdk_dir)
|
return os.path.isdir(sdk_dir)
|
||||||
|
|
||||||
def should_update_sdk_json():
|
def should_update_tool_json():
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
if os.path.exists(json_filepath):
|
if os.path.exists(json_filepath):
|
||||||
json_modification_time = os.path.getmtime(json_filepath)
|
json_modification_time = os.path.getmtime(json_filepath)
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@@ -168,10 +160,10 @@ def should_update_sdk_json():
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_sdk_json():
|
def update_tool_json():
|
||||||
global ttbuild_cdn, ttbuild_path
|
global ttbuild_cdn, ttbuild_path
|
||||||
json_url = f"{ttbuild_cdn}/sdk.json"
|
json_url = f"{ttbuild_cdn}/sdk/tool.json"
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
return download_file(json_url, json_filepath)
|
return download_file(json_url, json_filepath)
|
||||||
|
|
||||||
def should_fetch_sdkconfig_files(platform_targets):
|
def should_fetch_sdkconfig_files(platform_targets):
|
||||||
@@ -206,16 +198,6 @@ def validate_environment():
|
|||||||
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
||||||
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
||||||
|
|
||||||
def validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
|
|
||||||
version_map = sdk_json["versions"]
|
|
||||||
if not sdk_version in version_map:
|
|
||||||
exit_with_error(f"Version not found: {sdk_version}")
|
|
||||||
version_data = version_map[sdk_version]
|
|
||||||
available_platforms = version_data["platforms"]
|
|
||||||
for desired_platform in platforms_to_build:
|
|
||||||
if not desired_platform in available_platforms:
|
|
||||||
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
|
|
||||||
|
|
||||||
def validate_self(sdk_json):
|
def validate_self(sdk_json):
|
||||||
if not "toolVersion" in sdk_json:
|
if not "toolVersion" in sdk_json:
|
||||||
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
||||||
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
|
|||||||
def sdk_download(version, platform):
|
def sdk_download(version, platform):
|
||||||
sdk_root_dir = get_sdk_root_dir(version, platform)
|
sdk_root_dir = get_sdk_root_dir(version, platform)
|
||||||
os.makedirs(sdk_root_dir, exist_ok=True)
|
os.makedirs(sdk_root_dir, exist_ok=True)
|
||||||
sdk_url = get_sdk_url(version, platform)
|
sdk_index_url = get_sdk_url(version, "index.json")
|
||||||
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
|
||||||
print(f"Downloading SDK version {version} for {platform}")
|
print(f"Downloading SDK version {version} for {platform}")
|
||||||
if download_file(sdk_url, filepath):
|
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
|
||||||
with zipfile.ZipFile(filepath, "r") as zip_ref:
|
if verbose:
|
||||||
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
|
||||||
return True
|
if not download_file(sdk_index_url, sdk_index_filepath):
|
||||||
else:
|
# TODO: 404 check, print a more accurate error
|
||||||
|
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
|
||||||
return False
|
return False
|
||||||
|
with open(sdk_index_filepath) as sdk_index_json_file:
|
||||||
|
sdk_index_json = json.load(sdk_index_json_file)
|
||||||
|
sdk_platforms = sdk_index_json["platforms"]
|
||||||
|
if platform not in sdk_platforms:
|
||||||
|
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
|
||||||
|
return False
|
||||||
|
sdk_platform_file = sdk_platforms[platform]
|
||||||
|
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
|
||||||
|
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
||||||
|
if verbose:
|
||||||
|
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
|
||||||
|
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
return False
|
||||||
|
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
|
||||||
|
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
||||||
|
return True
|
||||||
|
|
||||||
def sdk_download_all(version, platforms):
|
def sdk_download_all(version, platforms):
|
||||||
for platform in platforms:
|
for platform in platforms:
|
||||||
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "build"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "elf"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
print_status_success(f"Building {platform} ELF")
|
print_status_success(f"Building {platform} ELF")
|
||||||
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
|
|||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
sdk_json = read_sdk_json()
|
sdk_json = read_sdk_json()
|
||||||
validate_self(sdk_json)
|
validate_self(sdk_json)
|
||||||
if not "versions" in sdk_json:
|
|
||||||
exit_with_error("Version data not found in sdk.json")
|
|
||||||
# Build
|
# Build
|
||||||
sdk_version = manifest["target"]["sdk"]
|
sdk_version = manifest["target"]["sdk"]
|
||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build)
|
|
||||||
if not sdk_download_all(sdk_version, platforms_to_build):
|
if not sdk_download_all(sdk_version, platforms_to_build):
|
||||||
exit_with_error("Failed to download one or more SDKs")
|
exit_with_error("Failed to download one or more SDKs")
|
||||||
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
||||||
@@ -613,7 +615,7 @@ if __name__ == "__main__":
|
|||||||
# Argument validation
|
# Argument validation
|
||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 1:
|
||||||
print_help()
|
print_help()
|
||||||
sys.exit()
|
sys.exit(1)
|
||||||
if "--verbose" in sys.argv:
|
if "--verbose" in sys.argv:
|
||||||
verbose = True
|
verbose = True
|
||||||
sys.argv.remove("--verbose")
|
sys.argv.remove("--verbose")
|
||||||
@@ -633,8 +635,8 @@ if __name__ == "__main__":
|
|||||||
manifest = read_manifest()
|
manifest = read_manifest()
|
||||||
validate_manifest(manifest)
|
validate_manifest(manifest)
|
||||||
all_platform_targets = manifest["target"]["platforms"].split(",")
|
all_platform_targets = manifest["target"]["platforms"].split(",")
|
||||||
# Update SDK cache (sdk.json)
|
# Update SDK cache (tool.json)
|
||||||
if should_update_sdk_json() and not update_sdk_json():
|
if should_update_tool_json() and not update_tool_json():
|
||||||
exit_with_error("Failed to retrieve SDK info")
|
exit_with_error("Failed to retrieve SDK info")
|
||||||
# Actions
|
# Actions
|
||||||
if action_arg == "build":
|
if action_arg == "build":
|
||||||
@@ -644,7 +646,8 @@ if __name__ == "__main__":
|
|||||||
platform = None
|
platform = None
|
||||||
if len(sys.argv) > 2:
|
if len(sys.argv) > 2:
|
||||||
platform = sys.argv[2]
|
platform = sys.argv[2]
|
||||||
build_action(manifest, platform)
|
if not build_action(manifest, platform):
|
||||||
|
sys.exit(1)
|
||||||
elif action_arg == "clean":
|
elif action_arg == "clean":
|
||||||
clean_action()
|
clean_action()
|
||||||
elif action_arg == "clearcache":
|
elif action_arg == "clearcache":
|
||||||
|
|||||||
@@ -14,4 +14,3 @@ set(EXTRA_COMPONENT_DIRS ${TACTILITY_SDK_PATH})
|
|||||||
|
|
||||||
project(Diceware)
|
project(Diceware)
|
||||||
tactility_project(Diceware)
|
tactility_project(Diceware)
|
||||||
|
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES
|
file(GLOB_RECURSE SOURCE_FILES
|
||||||
Source/*.c*
|
Source/*.c*
|
||||||
# Library source files must be included directly,
|
|
||||||
# because all regular dependencies get stripped by elf_loader's cmake script
|
|
||||||
../../../Libraries/Str/Source/*.c**
|
|
||||||
)
|
)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
# Library headers must be included directly,
|
# Library headers must be included directly,
|
||||||
# because all regular dependencies get stripped by elf_loader's cmake script
|
# because all regular dependencies get stripped by elf_loader's cmake script
|
||||||
INCLUDE_DIRS ../../../Libraries/Str/Include
|
|
||||||
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
|
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
|
||||||
REQUIRES TactilitySDK
|
REQUIRES TactilitySDK
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include <esp_random.h>
|
#include <esp_random.h>
|
||||||
#include <esp_log.h>
|
#include <esp_log.h>
|
||||||
|
|
||||||
|
#include <Tactility/kernel/Kernel.h>
|
||||||
|
|
||||||
constexpr char* TAG = "Diceware";
|
constexpr char* TAG = "Diceware";
|
||||||
|
|
||||||
static void skipNewlines(FILE* file, const int count) {
|
static void skipNewlines(FILE* file, const int count) {
|
||||||
@@ -20,15 +22,15 @@ static void skipNewlines(FILE* file, const int count) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Str readWord(FILE* file) {
|
static std::string readWord(FILE* file) {
|
||||||
char c;
|
char c;
|
||||||
Str result;
|
std::string result;
|
||||||
// Read word until newline
|
// Read word until newline
|
||||||
while (fread(&c, 1, 1, file) && c != '\n') { result.append(c); }
|
while (fread(&c, 1, 1, file) && c != '\n') { result += c; }
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Str readWordAtLine(const AppHandle handle, const int lineIndex) {
|
static std::string readWordAtLine(const AppHandle handle, const int lineIndex) {
|
||||||
char path[256];
|
char path[256];
|
||||||
size_t size = 256;
|
size_t size = 256;
|
||||||
tt_app_get_assets_child_path(handle, "eff_large_wordlist.txt", path, &size);
|
tt_app_get_assets_child_path(handle, "eff_large_wordlist.txt", path, &size);
|
||||||
@@ -38,8 +40,8 @@ static Str readWordAtLine(const AppHandle handle, const int lineIndex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto lock = tt_lock_alloc_for_path(path);
|
auto lock = tt_lock_alloc_for_path(path);
|
||||||
Str word;
|
std::string word;
|
||||||
if (tt_lock_acquire(lock, TT_MAX_TICKS)) {
|
if (tt_lock_acquire(lock, tt::kernel::MAX_TICKS)) {
|
||||||
FILE* file = fopen(path, "r");
|
FILE* file = fopen(path, "r");
|
||||||
if (file != nullptr) {
|
if (file != nullptr) {
|
||||||
skipNewlines(file, lineIndex);
|
skipNewlines(file, lineIndex);
|
||||||
@@ -52,25 +54,24 @@ static Str readWordAtLine(const AppHandle handle, const int lineIndex) {
|
|||||||
return word;
|
return word;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t Diceware::jobMain(void* data) {
|
int32_t Diceware::jobMain() {
|
||||||
Diceware* application = static_cast<Diceware*>(data);
|
std::string result;
|
||||||
Str result;
|
for (int i = 0; i < wordCount; i++) {
|
||||||
for (int i = 0; i < application->wordCount; i++) {
|
|
||||||
constexpr int line_count = 7776;
|
constexpr int line_count = 7776;
|
||||||
const auto line_index = esp_random() % line_count;
|
const auto line_index = esp_random() % line_count;
|
||||||
auto word = readWordAtLine(application->handle, line_index);
|
auto word = readWordAtLine(handle, line_index);
|
||||||
result.appendf("%s ", word.c_str());
|
result += word;
|
||||||
|
result += " ";
|
||||||
}
|
}
|
||||||
|
|
||||||
application->onFinishJob(result);
|
onFinishJob(result);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Diceware::cleanupJob() {
|
void Diceware::cleanupJob() {
|
||||||
if (jobThread != nullptr) {
|
if (jobThread != nullptr) {
|
||||||
tt_thread_join(jobThread, TT_MAX_TICKS);
|
jobThread->join();
|
||||||
tt_thread_free(jobThread);
|
|
||||||
jobThread = nullptr;
|
jobThread = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,12 +80,14 @@ void Diceware::startJob(uint32_t jobWordCount) {
|
|||||||
cleanupJob();
|
cleanupJob();
|
||||||
|
|
||||||
wordCount = jobWordCount;
|
wordCount = jobWordCount;
|
||||||
jobThread = tt_thread_alloc_ext("Diceware", 4096, jobMain, this);
|
jobThread = std::make_unique<tt::Thread>("Diceware", 4096, [this] {
|
||||||
tt_thread_start(jobThread);
|
return jobMain();
|
||||||
|
});
|
||||||
|
jobThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Diceware::onFinishJob(Str result) {
|
void Diceware::onFinishJob(std::string result) {
|
||||||
tt_lvgl_lock(TT_MAX_TICKS);
|
tt_lvgl_lock(tt::kernel::MAX_TICKS);
|
||||||
lv_label_set_text(resultLabel, result.c_str());
|
lv_label_set_text(resultLabel, result.c_str());
|
||||||
tt_lvgl_unlock();
|
tt_lvgl_unlock();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "tt_app.h"
|
#include "tt_app.h"
|
||||||
#include "tt_thread.h"
|
|
||||||
|
|
||||||
#include <Str.h>
|
#include <Tactility/Thread.h>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
#include <TactilityCpp/App.h>
|
#include <TactilityCpp/App.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
class Diceware final : public App {
|
class Diceware final : public App {
|
||||||
|
|
||||||
AppHandle handle = nullptr;
|
AppHandle handle = nullptr;
|
||||||
lv_obj_t* spinbox = nullptr;
|
lv_obj_t* spinbox = nullptr;
|
||||||
lv_obj_t* resultLabel = nullptr;
|
lv_obj_t* resultLabel = nullptr;
|
||||||
ThreadHandle jobThread = nullptr;
|
std::unique_ptr<tt::Thread> jobThread = nullptr;
|
||||||
uint32_t wordCount = 5;
|
uint32_t wordCount = 5;
|
||||||
|
|
||||||
static void onClickGenerate(lv_event_t* e);
|
static void onClickGenerate(lv_event_t* e);
|
||||||
@@ -20,10 +23,10 @@ class Diceware final : public App {
|
|||||||
static void onSpinboxIncrement(lv_event_t* e);
|
static void onSpinboxIncrement(lv_event_t* e);
|
||||||
static void onHelpClicked(lv_event_t* e);
|
static void onHelpClicked(lv_event_t* e);
|
||||||
|
|
||||||
static int32_t jobMain(void* data);
|
int32_t jobMain();
|
||||||
|
|
||||||
void startJob(uint32_t jobWordCount);
|
void startJob(uint32_t jobWordCount);
|
||||||
void onFinishJob(Str result);
|
void onFinishJob(std::string result);
|
||||||
void cleanupJob();
|
void cleanupJob();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
[manifest]
|
[manifest]
|
||||||
version=0.1
|
version=0.1
|
||||||
[target]
|
[target]
|
||||||
sdk=0.6.0
|
sdk=0.7.0-dev
|
||||||
platforms=esp32,esp32s3
|
platforms=esp32,esp32s3,esp32c6,esp32p4
|
||||||
[app]
|
[app]
|
||||||
id=one.tactility.diceware
|
id=one.tactility.diceware
|
||||||
versionName=0.2.0
|
versionName=0.3.0
|
||||||
versionCode=2
|
versionCode=3
|
||||||
name=Diceware
|
name=Diceware
|
||||||
|
|||||||
+54
-51
@@ -12,7 +12,7 @@ import requests
|
|||||||
import tarfile
|
import tarfile
|
||||||
|
|
||||||
ttbuild_path = ".tactility"
|
ttbuild_path = ".tactility"
|
||||||
ttbuild_version = "2.5.0"
|
ttbuild_version = "3.1.0"
|
||||||
ttbuild_cdn = "https://cdn.tactility.one"
|
ttbuild_cdn = "https://cdn.tactility.one"
|
||||||
ttbuild_sdk_json_validity = 3600 # seconds
|
ttbuild_sdk_json_validity = 3600 # seconds
|
||||||
ttport = 6666
|
ttport = 6666
|
||||||
@@ -20,20 +20,12 @@ verbose = False
|
|||||||
use_local_sdk = False
|
use_local_sdk = False
|
||||||
local_base_path = None
|
local_base_path = None
|
||||||
|
|
||||||
if sys.platform == "win32":
|
shell_color_red = "\033[91m"
|
||||||
shell_color_red = "\033[91m"
|
shell_color_orange = "\033[93m"
|
||||||
shell_color_orange = "\033[93m"
|
shell_color_green = "\033[32m"
|
||||||
shell_color_green = "\033[32m"
|
shell_color_purple = "\033[35m"
|
||||||
shell_color_purple = "\033[35m"
|
shell_color_cyan = "\033[36m"
|
||||||
shell_color_cyan = "\033[36m"
|
shell_color_reset = "\033[m"
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
else:
|
|
||||||
shell_color_red = "\033[91m"
|
|
||||||
shell_color_orange = "\033[93m"
|
|
||||||
shell_color_green = "\033[32m"
|
|
||||||
shell_color_purple = "\033[35m"
|
|
||||||
shell_color_cyan = "\033[36m"
|
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
|
|
||||||
def print_help():
|
def print_help():
|
||||||
print("Usage: python tactility.py [action] [options]")
|
print("Usage: python tactility.py [action] [options]")
|
||||||
@@ -115,9 +107,9 @@ def read_properties_file(path):
|
|||||||
#region SDK helpers
|
#region SDK helpers
|
||||||
|
|
||||||
def read_sdk_json():
|
def read_sdk_json():
|
||||||
json_file_path = os.path.join(ttbuild_path, "sdk.json")
|
json_file_path = os.path.join(ttbuild_path, "tool.json")
|
||||||
json_file = open(json_file_path)
|
with open(json_file_path) as json_file:
|
||||||
return json.load(json_file)
|
return json.load(json_file)
|
||||||
|
|
||||||
def get_sdk_dir(version, platform):
|
def get_sdk_dir(version, platform):
|
||||||
global use_local_sdk, local_base_path
|
global use_local_sdk, local_base_path
|
||||||
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
|
|||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
||||||
|
|
||||||
def get_sdk_url(version, platform):
|
def get_sdk_url(version, file):
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
|
return f"{ttbuild_cdn}/sdk/{version}/{file}"
|
||||||
|
|
||||||
def sdk_exists(version, platform):
|
def sdk_exists(version, platform):
|
||||||
sdk_dir = get_sdk_dir(version, platform)
|
sdk_dir = get_sdk_dir(version, platform)
|
||||||
return os.path.isdir(sdk_dir)
|
return os.path.isdir(sdk_dir)
|
||||||
|
|
||||||
def should_update_sdk_json():
|
def should_update_tool_json():
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
if os.path.exists(json_filepath):
|
if os.path.exists(json_filepath):
|
||||||
json_modification_time = os.path.getmtime(json_filepath)
|
json_modification_time = os.path.getmtime(json_filepath)
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@@ -168,10 +160,10 @@ def should_update_sdk_json():
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_sdk_json():
|
def update_tool_json():
|
||||||
global ttbuild_cdn, ttbuild_path
|
global ttbuild_cdn, ttbuild_path
|
||||||
json_url = f"{ttbuild_cdn}/sdk.json"
|
json_url = f"{ttbuild_cdn}/sdk/tool.json"
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
return download_file(json_url, json_filepath)
|
return download_file(json_url, json_filepath)
|
||||||
|
|
||||||
def should_fetch_sdkconfig_files(platform_targets):
|
def should_fetch_sdkconfig_files(platform_targets):
|
||||||
@@ -206,16 +198,6 @@ def validate_environment():
|
|||||||
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
||||||
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
||||||
|
|
||||||
def validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
|
|
||||||
version_map = sdk_json["versions"]
|
|
||||||
if not sdk_version in version_map:
|
|
||||||
exit_with_error(f"Version not found: {sdk_version}")
|
|
||||||
version_data = version_map[sdk_version]
|
|
||||||
available_platforms = version_data["platforms"]
|
|
||||||
for desired_platform in platforms_to_build:
|
|
||||||
if not desired_platform in available_platforms:
|
|
||||||
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
|
|
||||||
|
|
||||||
def validate_self(sdk_json):
|
def validate_self(sdk_json):
|
||||||
if not "toolVersion" in sdk_json:
|
if not "toolVersion" in sdk_json:
|
||||||
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
||||||
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
|
|||||||
def sdk_download(version, platform):
|
def sdk_download(version, platform):
|
||||||
sdk_root_dir = get_sdk_root_dir(version, platform)
|
sdk_root_dir = get_sdk_root_dir(version, platform)
|
||||||
os.makedirs(sdk_root_dir, exist_ok=True)
|
os.makedirs(sdk_root_dir, exist_ok=True)
|
||||||
sdk_url = get_sdk_url(version, platform)
|
sdk_index_url = get_sdk_url(version, "index.json")
|
||||||
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
|
||||||
print(f"Downloading SDK version {version} for {platform}")
|
print(f"Downloading SDK version {version} for {platform}")
|
||||||
if download_file(sdk_url, filepath):
|
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
|
||||||
with zipfile.ZipFile(filepath, "r") as zip_ref:
|
if verbose:
|
||||||
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
|
||||||
return True
|
if not download_file(sdk_index_url, sdk_index_filepath):
|
||||||
else:
|
# TODO: 404 check, print a more accurate error
|
||||||
|
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
|
||||||
return False
|
return False
|
||||||
|
with open(sdk_index_filepath) as sdk_index_json_file:
|
||||||
|
sdk_index_json = json.load(sdk_index_json_file)
|
||||||
|
sdk_platforms = sdk_index_json["platforms"]
|
||||||
|
if platform not in sdk_platforms:
|
||||||
|
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
|
||||||
|
return False
|
||||||
|
sdk_platform_file = sdk_platforms[platform]
|
||||||
|
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
|
||||||
|
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
||||||
|
if verbose:
|
||||||
|
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
|
||||||
|
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
return False
|
||||||
|
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
|
||||||
|
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
||||||
|
return True
|
||||||
|
|
||||||
def sdk_download_all(version, platforms):
|
def sdk_download_all(version, platforms):
|
||||||
for platform in platforms:
|
for platform in platforms:
|
||||||
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "build"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "elf"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
print_status_success(f"Building {platform} ELF")
|
print_status_success(f"Building {platform} ELF")
|
||||||
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
|
|||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
sdk_json = read_sdk_json()
|
sdk_json = read_sdk_json()
|
||||||
validate_self(sdk_json)
|
validate_self(sdk_json)
|
||||||
if not "versions" in sdk_json:
|
|
||||||
exit_with_error("Version data not found in sdk.json")
|
|
||||||
# Build
|
# Build
|
||||||
sdk_version = manifest["target"]["sdk"]
|
sdk_version = manifest["target"]["sdk"]
|
||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build)
|
|
||||||
if not sdk_download_all(sdk_version, platforms_to_build):
|
if not sdk_download_all(sdk_version, platforms_to_build):
|
||||||
exit_with_error("Failed to download one or more SDKs")
|
exit_with_error("Failed to download one or more SDKs")
|
||||||
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
||||||
@@ -613,7 +615,7 @@ if __name__ == "__main__":
|
|||||||
# Argument validation
|
# Argument validation
|
||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 1:
|
||||||
print_help()
|
print_help()
|
||||||
sys.exit()
|
sys.exit(1)
|
||||||
if "--verbose" in sys.argv:
|
if "--verbose" in sys.argv:
|
||||||
verbose = True
|
verbose = True
|
||||||
sys.argv.remove("--verbose")
|
sys.argv.remove("--verbose")
|
||||||
@@ -633,8 +635,8 @@ if __name__ == "__main__":
|
|||||||
manifest = read_manifest()
|
manifest = read_manifest()
|
||||||
validate_manifest(manifest)
|
validate_manifest(manifest)
|
||||||
all_platform_targets = manifest["target"]["platforms"].split(",")
|
all_platform_targets = manifest["target"]["platforms"].split(",")
|
||||||
# Update SDK cache (sdk.json)
|
# Update SDK cache (tool.json)
|
||||||
if should_update_sdk_json() and not update_sdk_json():
|
if should_update_tool_json() and not update_tool_json():
|
||||||
exit_with_error("Failed to retrieve SDK info")
|
exit_with_error("Failed to retrieve SDK info")
|
||||||
# Actions
|
# Actions
|
||||||
if action_arg == "build":
|
if action_arg == "build":
|
||||||
@@ -644,7 +646,8 @@ if __name__ == "__main__":
|
|||||||
platform = None
|
platform = None
|
||||||
if len(sys.argv) > 2:
|
if len(sys.argv) > 2:
|
||||||
platform = sys.argv[2]
|
platform = sys.argv[2]
|
||||||
build_action(manifest, platform)
|
if not build_action(manifest, platform):
|
||||||
|
sys.exit(1)
|
||||||
elif action_arg == "clean":
|
elif action_arg == "clean":
|
||||||
clean_action()
|
clean_action()
|
||||||
elif action_arg == "clearcache":
|
elif action_arg == "clearcache":
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES
|
file(GLOB_RECURSE SOURCE_FILES
|
||||||
Source/*.c*
|
Source/*.c*
|
||||||
# Library source files must be included directly,
|
|
||||||
# because all regular dependencies get stripped by elf_loader's cmake script
|
|
||||||
../../../Libraries/Str/Source/*.c**
|
|
||||||
../../../Libraries/TactilityCpp/Source/*.c**
|
|
||||||
)
|
)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
# Library headers must be included directly,
|
# Library headers must be included directly,
|
||||||
# because all regular dependencies get stripped by elf_loader's cmake script
|
# because all regular dependencies get stripped by elf_loader's cmake script
|
||||||
INCLUDE_DIRS ../../../Libraries/Str/Include
|
|
||||||
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
|
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
|
||||||
REQUIRES TactilitySDK
|
REQUIRES TactilitySDK
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "Gpio.h"
|
#include "Gpio.h"
|
||||||
|
|
||||||
#include <tt_app_alertdialog.h>
|
#include <Tactility/kernel/Kernel.h>
|
||||||
|
|
||||||
#include <tt_hal.h>
|
#include <tt_hal.h>
|
||||||
#include <tt_hal_gpio.h>
|
#include <tt_hal_gpio.h>
|
||||||
#include <tt_lvgl.h>
|
#include <tt_lvgl.h>
|
||||||
@@ -18,7 +19,7 @@ void Gpio::updatePinStates() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Gpio::updatePinWidgets() {
|
void Gpio::updatePinWidgets() {
|
||||||
tt_lvgl_lock(TT_MAX_TICKS);
|
tt_lvgl_lock(tt::kernel::MAX_TICKS);
|
||||||
for (int j = 0; j < pinStates.size(); ++j) {
|
for (int j = 0; j < pinStates.size(); ++j) {
|
||||||
int level = pinStates[j];
|
int level = pinStates[j];
|
||||||
lv_obj_t* label = pinWidgets[j];
|
lv_obj_t* label = pinWidgets[j];
|
||||||
@@ -46,28 +47,21 @@ lv_obj_t* Gpio::createGpioRowWrapper(lv_obj_t* parent) {
|
|||||||
|
|
||||||
// region Task
|
// region Task
|
||||||
|
|
||||||
void Gpio::onTimer(void* context) {
|
void Gpio::onTimer() {
|
||||||
Gpio* app = static_cast<Gpio*>(context);
|
mutex.lock();
|
||||||
|
updatePinStates();
|
||||||
app->mutex.lock();
|
updatePinWidgets();
|
||||||
app->updatePinStates();
|
mutex.unlock();
|
||||||
app->updatePinWidgets();
|
|
||||||
app->mutex.unlock();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gpio::startTask() {
|
void Gpio::startTask() {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
assert(timer == nullptr);
|
timer.start();
|
||||||
timer = tt_timer_alloc(TimerTypePeriodic, onTimer, this);
|
|
||||||
tt_timer_start(timer, 100 / portTICK_PERIOD_MS);
|
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Gpio::stopTask() {
|
void Gpio::stopTask() {
|
||||||
assert(timer);
|
timer.stop();
|
||||||
tt_timer_stop(timer);
|
|
||||||
tt_timer_free(timer);
|
|
||||||
timer = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// endregion Task
|
// endregion Task
|
||||||
|
|||||||
@@ -3,9 +3,9 @@
|
|||||||
#include <TactilityCpp/App.h>
|
#include <TactilityCpp/App.h>
|
||||||
|
|
||||||
#include <tt_app.h>
|
#include <tt_app.h>
|
||||||
#include <tt_timer.h>
|
|
||||||
|
|
||||||
#include <TactilityCpp/Mutex.h>
|
#include <Tactility/RecursiveMutex.h>
|
||||||
|
#include <Tactility/Timer.h>
|
||||||
|
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -14,11 +14,13 @@ class Gpio final : public App {
|
|||||||
|
|
||||||
std::vector<lv_obj_t*> pinWidgets;
|
std::vector<lv_obj_t*> pinWidgets;
|
||||||
std::vector<bool> pinStates;
|
std::vector<bool> pinStates;
|
||||||
TimerHandle timer;
|
tt::Timer timer = tt::Timer(tt::Timer::Type::Periodic, pdMS_TO_TICKS(100), [this]{
|
||||||
Mutex mutex = Mutex(MutexTypeRecursive);
|
onTimer();
|
||||||
|
});
|
||||||
|
tt::RecursiveMutex mutex;
|
||||||
|
|
||||||
static lv_obj_t* createGpioRowWrapper(lv_obj_t* parent);
|
static lv_obj_t* createGpioRowWrapper(lv_obj_t* parent);
|
||||||
static void onTimer(void* parameter);
|
void onTimer();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
[manifest]
|
[manifest]
|
||||||
version=0.1
|
version=0.1
|
||||||
[target]
|
[target]
|
||||||
sdk=0.6.0
|
sdk=0.7.0-dev
|
||||||
platforms=esp32,esp32s3
|
platforms=esp32,esp32s3,esp32c6,esp32p4
|
||||||
[app]
|
[app]
|
||||||
id=one.tactility.gpio
|
id=one.tactility.gpio
|
||||||
versionName=0.2.0
|
versionName=0.3.0
|
||||||
versionCode=2
|
versionCode=3
|
||||||
name=GPIO
|
name=GPIO
|
||||||
|
|||||||
+54
-51
@@ -12,7 +12,7 @@ import requests
|
|||||||
import tarfile
|
import tarfile
|
||||||
|
|
||||||
ttbuild_path = ".tactility"
|
ttbuild_path = ".tactility"
|
||||||
ttbuild_version = "2.5.0"
|
ttbuild_version = "3.1.0"
|
||||||
ttbuild_cdn = "https://cdn.tactility.one"
|
ttbuild_cdn = "https://cdn.tactility.one"
|
||||||
ttbuild_sdk_json_validity = 3600 # seconds
|
ttbuild_sdk_json_validity = 3600 # seconds
|
||||||
ttport = 6666
|
ttport = 6666
|
||||||
@@ -20,20 +20,12 @@ verbose = False
|
|||||||
use_local_sdk = False
|
use_local_sdk = False
|
||||||
local_base_path = None
|
local_base_path = None
|
||||||
|
|
||||||
if sys.platform == "win32":
|
shell_color_red = "\033[91m"
|
||||||
shell_color_red = "\033[91m"
|
shell_color_orange = "\033[93m"
|
||||||
shell_color_orange = "\033[93m"
|
shell_color_green = "\033[32m"
|
||||||
shell_color_green = "\033[32m"
|
shell_color_purple = "\033[35m"
|
||||||
shell_color_purple = "\033[35m"
|
shell_color_cyan = "\033[36m"
|
||||||
shell_color_cyan = "\033[36m"
|
shell_color_reset = "\033[m"
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
else:
|
|
||||||
shell_color_red = "\033[91m"
|
|
||||||
shell_color_orange = "\033[93m"
|
|
||||||
shell_color_green = "\033[32m"
|
|
||||||
shell_color_purple = "\033[35m"
|
|
||||||
shell_color_cyan = "\033[36m"
|
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
|
|
||||||
def print_help():
|
def print_help():
|
||||||
print("Usage: python tactility.py [action] [options]")
|
print("Usage: python tactility.py [action] [options]")
|
||||||
@@ -115,9 +107,9 @@ def read_properties_file(path):
|
|||||||
#region SDK helpers
|
#region SDK helpers
|
||||||
|
|
||||||
def read_sdk_json():
|
def read_sdk_json():
|
||||||
json_file_path = os.path.join(ttbuild_path, "sdk.json")
|
json_file_path = os.path.join(ttbuild_path, "tool.json")
|
||||||
json_file = open(json_file_path)
|
with open(json_file_path) as json_file:
|
||||||
return json.load(json_file)
|
return json.load(json_file)
|
||||||
|
|
||||||
def get_sdk_dir(version, platform):
|
def get_sdk_dir(version, platform):
|
||||||
global use_local_sdk, local_base_path
|
global use_local_sdk, local_base_path
|
||||||
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
|
|||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
||||||
|
|
||||||
def get_sdk_url(version, platform):
|
def get_sdk_url(version, file):
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
|
return f"{ttbuild_cdn}/sdk/{version}/{file}"
|
||||||
|
|
||||||
def sdk_exists(version, platform):
|
def sdk_exists(version, platform):
|
||||||
sdk_dir = get_sdk_dir(version, platform)
|
sdk_dir = get_sdk_dir(version, platform)
|
||||||
return os.path.isdir(sdk_dir)
|
return os.path.isdir(sdk_dir)
|
||||||
|
|
||||||
def should_update_sdk_json():
|
def should_update_tool_json():
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
if os.path.exists(json_filepath):
|
if os.path.exists(json_filepath):
|
||||||
json_modification_time = os.path.getmtime(json_filepath)
|
json_modification_time = os.path.getmtime(json_filepath)
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@@ -168,10 +160,10 @@ def should_update_sdk_json():
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_sdk_json():
|
def update_tool_json():
|
||||||
global ttbuild_cdn, ttbuild_path
|
global ttbuild_cdn, ttbuild_path
|
||||||
json_url = f"{ttbuild_cdn}/sdk.json"
|
json_url = f"{ttbuild_cdn}/sdk/tool.json"
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
return download_file(json_url, json_filepath)
|
return download_file(json_url, json_filepath)
|
||||||
|
|
||||||
def should_fetch_sdkconfig_files(platform_targets):
|
def should_fetch_sdkconfig_files(platform_targets):
|
||||||
@@ -206,16 +198,6 @@ def validate_environment():
|
|||||||
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
||||||
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
||||||
|
|
||||||
def validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
|
|
||||||
version_map = sdk_json["versions"]
|
|
||||||
if not sdk_version in version_map:
|
|
||||||
exit_with_error(f"Version not found: {sdk_version}")
|
|
||||||
version_data = version_map[sdk_version]
|
|
||||||
available_platforms = version_data["platforms"]
|
|
||||||
for desired_platform in platforms_to_build:
|
|
||||||
if not desired_platform in available_platforms:
|
|
||||||
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
|
|
||||||
|
|
||||||
def validate_self(sdk_json):
|
def validate_self(sdk_json):
|
||||||
if not "toolVersion" in sdk_json:
|
if not "toolVersion" in sdk_json:
|
||||||
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
||||||
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
|
|||||||
def sdk_download(version, platform):
|
def sdk_download(version, platform):
|
||||||
sdk_root_dir = get_sdk_root_dir(version, platform)
|
sdk_root_dir = get_sdk_root_dir(version, platform)
|
||||||
os.makedirs(sdk_root_dir, exist_ok=True)
|
os.makedirs(sdk_root_dir, exist_ok=True)
|
||||||
sdk_url = get_sdk_url(version, platform)
|
sdk_index_url = get_sdk_url(version, "index.json")
|
||||||
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
|
||||||
print(f"Downloading SDK version {version} for {platform}")
|
print(f"Downloading SDK version {version} for {platform}")
|
||||||
if download_file(sdk_url, filepath):
|
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
|
||||||
with zipfile.ZipFile(filepath, "r") as zip_ref:
|
if verbose:
|
||||||
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
|
||||||
return True
|
if not download_file(sdk_index_url, sdk_index_filepath):
|
||||||
else:
|
# TODO: 404 check, print a more accurate error
|
||||||
|
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
|
||||||
return False
|
return False
|
||||||
|
with open(sdk_index_filepath) as sdk_index_json_file:
|
||||||
|
sdk_index_json = json.load(sdk_index_json_file)
|
||||||
|
sdk_platforms = sdk_index_json["platforms"]
|
||||||
|
if platform not in sdk_platforms:
|
||||||
|
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
|
||||||
|
return False
|
||||||
|
sdk_platform_file = sdk_platforms[platform]
|
||||||
|
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
|
||||||
|
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
||||||
|
if verbose:
|
||||||
|
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
|
||||||
|
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
return False
|
||||||
|
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
|
||||||
|
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
||||||
|
return True
|
||||||
|
|
||||||
def sdk_download_all(version, platforms):
|
def sdk_download_all(version, platforms):
|
||||||
for platform in platforms:
|
for platform in platforms:
|
||||||
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "build"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "elf"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
print_status_success(f"Building {platform} ELF")
|
print_status_success(f"Building {platform} ELF")
|
||||||
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
|
|||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
sdk_json = read_sdk_json()
|
sdk_json = read_sdk_json()
|
||||||
validate_self(sdk_json)
|
validate_self(sdk_json)
|
||||||
if not "versions" in sdk_json:
|
|
||||||
exit_with_error("Version data not found in sdk.json")
|
|
||||||
# Build
|
# Build
|
||||||
sdk_version = manifest["target"]["sdk"]
|
sdk_version = manifest["target"]["sdk"]
|
||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build)
|
|
||||||
if not sdk_download_all(sdk_version, platforms_to_build):
|
if not sdk_download_all(sdk_version, platforms_to_build):
|
||||||
exit_with_error("Failed to download one or more SDKs")
|
exit_with_error("Failed to download one or more SDKs")
|
||||||
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
||||||
@@ -613,7 +615,7 @@ if __name__ == "__main__":
|
|||||||
# Argument validation
|
# Argument validation
|
||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 1:
|
||||||
print_help()
|
print_help()
|
||||||
sys.exit()
|
sys.exit(1)
|
||||||
if "--verbose" in sys.argv:
|
if "--verbose" in sys.argv:
|
||||||
verbose = True
|
verbose = True
|
||||||
sys.argv.remove("--verbose")
|
sys.argv.remove("--verbose")
|
||||||
@@ -633,8 +635,8 @@ if __name__ == "__main__":
|
|||||||
manifest = read_manifest()
|
manifest = read_manifest()
|
||||||
validate_manifest(manifest)
|
validate_manifest(manifest)
|
||||||
all_platform_targets = manifest["target"]["platforms"].split(",")
|
all_platform_targets = manifest["target"]["platforms"].split(",")
|
||||||
# Update SDK cache (sdk.json)
|
# Update SDK cache (tool.json)
|
||||||
if should_update_sdk_json() and not update_sdk_json():
|
if should_update_tool_json() and not update_tool_json():
|
||||||
exit_with_error("Failed to retrieve SDK info")
|
exit_with_error("Failed to retrieve SDK info")
|
||||||
# Actions
|
# Actions
|
||||||
if action_arg == "build":
|
if action_arg == "build":
|
||||||
@@ -644,7 +646,8 @@ if __name__ == "__main__":
|
|||||||
platform = None
|
platform = None
|
||||||
if len(sys.argv) > 2:
|
if len(sys.argv) > 2:
|
||||||
platform = sys.argv[2]
|
platform = sys.argv[2]
|
||||||
build_action(manifest, platform)
|
if not build_action(manifest, platform):
|
||||||
|
sys.exit(1)
|
||||||
elif action_arg == "clean":
|
elif action_arg == "clean":
|
||||||
clean_action()
|
clean_action()
|
||||||
elif action_arg == "clearcache":
|
elif action_arg == "clearcache":
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ file(GLOB_RECURSE SOURCE_FILES Source/*.c*)
|
|||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRC_DIRS "Source"
|
SRC_DIRS "Source"
|
||||||
INCLUDE_DIRS "Include"
|
# Library headers must be included directly,
|
||||||
|
# because all regular dependencies get stripped by elf_loader's cmake script
|
||||||
|
INCLUDE_DIRS "Include" "../../../Libraries/TactilityCpp/Include"
|
||||||
REQUIRES TactilitySDK
|
REQUIRES TactilitySDK
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <tt_hal_display.h>
|
#include <tt_hal_display.h>
|
||||||
|
#include <Tactility/kernel/Kernel.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for tt_hal_display_driver_*
|
* Wrapper for tt_hal_display_driver_*
|
||||||
@@ -22,7 +23,7 @@ public:
|
|||||||
tt_hal_display_driver_free(handle);
|
tt_hal_display_driver_free(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lock(TickType timeout = TT_MAX_TICKS) const {
|
bool lock(TickType_t timeout = tt::kernel::MAX_TICKS) const {
|
||||||
return tt_hal_display_driver_lock(handle, timeout);
|
return tt_hal_display_driver_lock(handle, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#include "PixelBuffer.h"
|
#include "PixelBuffer.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
#include <tt_kernel.h>
|
#include <Tactility/kernel/Kernel.h>
|
||||||
|
|
||||||
constexpr auto TAG = "Application";
|
constexpr auto TAG = "Application";
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ void runApplication(DisplayDriver* display, TouchDriver* touch) {
|
|||||||
|
|
||||||
// Give other tasks space to breathe
|
// Give other tasks space to breathe
|
||||||
// SPI displays would otherwise time out SPI SD card access
|
// SPI displays would otherwise time out SPI SD card access
|
||||||
tt_kernel_delay_ticks(1);
|
tt::kernel::delayTicks(1);
|
||||||
} while (!isTouched(touch));
|
} while (!isTouched(touch));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
[manifest]
|
[manifest]
|
||||||
version=0.1
|
version=0.1
|
||||||
[target]
|
[target]
|
||||||
sdk=0.6.0
|
sdk=0.7.0-dev
|
||||||
platforms=esp32,esp32s3
|
platforms=esp32,esp32s3,esp32c6,esp32p4
|
||||||
[app]
|
[app]
|
||||||
id=one.tactility.graphicsdemo
|
id=one.tactility.graphicsdemo
|
||||||
versionName=0.2.0
|
versionName=0.3.0
|
||||||
versionCode=2
|
versionCode=3
|
||||||
name=Graphics Demo
|
name=Graphics Demo
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import requests
|
|||||||
import tarfile
|
import tarfile
|
||||||
|
|
||||||
ttbuild_path = ".tactility"
|
ttbuild_path = ".tactility"
|
||||||
ttbuild_version = "2.5.0"
|
ttbuild_version = "3.1.0"
|
||||||
ttbuild_cdn = "https://cdn.tactility.one"
|
ttbuild_cdn = "https://cdn.tactility.one"
|
||||||
ttbuild_sdk_json_validity = 3600 # seconds
|
ttbuild_sdk_json_validity = 3600 # seconds
|
||||||
ttport = 6666
|
ttport = 6666
|
||||||
@@ -20,20 +20,12 @@ verbose = False
|
|||||||
use_local_sdk = False
|
use_local_sdk = False
|
||||||
local_base_path = None
|
local_base_path = None
|
||||||
|
|
||||||
if sys.platform == "win32":
|
shell_color_red = "\033[91m"
|
||||||
shell_color_red = "\033[91m"
|
shell_color_orange = "\033[93m"
|
||||||
shell_color_orange = "\033[93m"
|
shell_color_green = "\033[32m"
|
||||||
shell_color_green = "\033[32m"
|
shell_color_purple = "\033[35m"
|
||||||
shell_color_purple = "\033[35m"
|
shell_color_cyan = "\033[36m"
|
||||||
shell_color_cyan = "\033[36m"
|
shell_color_reset = "\033[m"
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
else:
|
|
||||||
shell_color_red = "\033[91m"
|
|
||||||
shell_color_orange = "\033[93m"
|
|
||||||
shell_color_green = "\033[32m"
|
|
||||||
shell_color_purple = "\033[35m"
|
|
||||||
shell_color_cyan = "\033[36m"
|
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
|
|
||||||
def print_help():
|
def print_help():
|
||||||
print("Usage: python tactility.py [action] [options]")
|
print("Usage: python tactility.py [action] [options]")
|
||||||
@@ -115,9 +107,9 @@ def read_properties_file(path):
|
|||||||
#region SDK helpers
|
#region SDK helpers
|
||||||
|
|
||||||
def read_sdk_json():
|
def read_sdk_json():
|
||||||
json_file_path = os.path.join(ttbuild_path, "sdk.json")
|
json_file_path = os.path.join(ttbuild_path, "tool.json")
|
||||||
json_file = open(json_file_path)
|
with open(json_file_path) as json_file:
|
||||||
return json.load(json_file)
|
return json.load(json_file)
|
||||||
|
|
||||||
def get_sdk_dir(version, platform):
|
def get_sdk_dir(version, platform):
|
||||||
global use_local_sdk, local_base_path
|
global use_local_sdk, local_base_path
|
||||||
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
|
|||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
||||||
|
|
||||||
def get_sdk_url(version, platform):
|
def get_sdk_url(version, file):
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
|
return f"{ttbuild_cdn}/sdk/{version}/{file}"
|
||||||
|
|
||||||
def sdk_exists(version, platform):
|
def sdk_exists(version, platform):
|
||||||
sdk_dir = get_sdk_dir(version, platform)
|
sdk_dir = get_sdk_dir(version, platform)
|
||||||
return os.path.isdir(sdk_dir)
|
return os.path.isdir(sdk_dir)
|
||||||
|
|
||||||
def should_update_sdk_json():
|
def should_update_tool_json():
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
if os.path.exists(json_filepath):
|
if os.path.exists(json_filepath):
|
||||||
json_modification_time = os.path.getmtime(json_filepath)
|
json_modification_time = os.path.getmtime(json_filepath)
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@@ -168,10 +160,10 @@ def should_update_sdk_json():
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_sdk_json():
|
def update_tool_json():
|
||||||
global ttbuild_cdn, ttbuild_path
|
global ttbuild_cdn, ttbuild_path
|
||||||
json_url = f"{ttbuild_cdn}/sdk.json"
|
json_url = f"{ttbuild_cdn}/sdk/tool.json"
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
return download_file(json_url, json_filepath)
|
return download_file(json_url, json_filepath)
|
||||||
|
|
||||||
def should_fetch_sdkconfig_files(platform_targets):
|
def should_fetch_sdkconfig_files(platform_targets):
|
||||||
@@ -206,16 +198,6 @@ def validate_environment():
|
|||||||
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
||||||
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
||||||
|
|
||||||
def validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
|
|
||||||
version_map = sdk_json["versions"]
|
|
||||||
if not sdk_version in version_map:
|
|
||||||
exit_with_error(f"Version not found: {sdk_version}")
|
|
||||||
version_data = version_map[sdk_version]
|
|
||||||
available_platforms = version_data["platforms"]
|
|
||||||
for desired_platform in platforms_to_build:
|
|
||||||
if not desired_platform in available_platforms:
|
|
||||||
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
|
|
||||||
|
|
||||||
def validate_self(sdk_json):
|
def validate_self(sdk_json):
|
||||||
if not "toolVersion" in sdk_json:
|
if not "toolVersion" in sdk_json:
|
||||||
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
||||||
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
|
|||||||
def sdk_download(version, platform):
|
def sdk_download(version, platform):
|
||||||
sdk_root_dir = get_sdk_root_dir(version, platform)
|
sdk_root_dir = get_sdk_root_dir(version, platform)
|
||||||
os.makedirs(sdk_root_dir, exist_ok=True)
|
os.makedirs(sdk_root_dir, exist_ok=True)
|
||||||
sdk_url = get_sdk_url(version, platform)
|
sdk_index_url = get_sdk_url(version, "index.json")
|
||||||
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
|
||||||
print(f"Downloading SDK version {version} for {platform}")
|
print(f"Downloading SDK version {version} for {platform}")
|
||||||
if download_file(sdk_url, filepath):
|
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
|
||||||
with zipfile.ZipFile(filepath, "r") as zip_ref:
|
if verbose:
|
||||||
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
|
||||||
return True
|
if not download_file(sdk_index_url, sdk_index_filepath):
|
||||||
else:
|
# TODO: 404 check, print a more accurate error
|
||||||
|
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
|
||||||
return False
|
return False
|
||||||
|
with open(sdk_index_filepath) as sdk_index_json_file:
|
||||||
|
sdk_index_json = json.load(sdk_index_json_file)
|
||||||
|
sdk_platforms = sdk_index_json["platforms"]
|
||||||
|
if platform not in sdk_platforms:
|
||||||
|
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
|
||||||
|
return False
|
||||||
|
sdk_platform_file = sdk_platforms[platform]
|
||||||
|
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
|
||||||
|
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
||||||
|
if verbose:
|
||||||
|
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
|
||||||
|
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
return False
|
||||||
|
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
|
||||||
|
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
||||||
|
return True
|
||||||
|
|
||||||
def sdk_download_all(version, platforms):
|
def sdk_download_all(version, platforms):
|
||||||
for platform in platforms:
|
for platform in platforms:
|
||||||
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "build"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "elf"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
print_status_success(f"Building {platform} ELF")
|
print_status_success(f"Building {platform} ELF")
|
||||||
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
|
|||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
sdk_json = read_sdk_json()
|
sdk_json = read_sdk_json()
|
||||||
validate_self(sdk_json)
|
validate_self(sdk_json)
|
||||||
if not "versions" in sdk_json:
|
|
||||||
exit_with_error("Version data not found in sdk.json")
|
|
||||||
# Build
|
# Build
|
||||||
sdk_version = manifest["target"]["sdk"]
|
sdk_version = manifest["target"]["sdk"]
|
||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build)
|
|
||||||
if not sdk_download_all(sdk_version, platforms_to_build):
|
if not sdk_download_all(sdk_version, platforms_to_build):
|
||||||
exit_with_error("Failed to download one or more SDKs")
|
exit_with_error("Failed to download one or more SDKs")
|
||||||
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
||||||
@@ -613,7 +615,7 @@ if __name__ == "__main__":
|
|||||||
# Argument validation
|
# Argument validation
|
||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 1:
|
||||||
print_help()
|
print_help()
|
||||||
sys.exit()
|
sys.exit(1)
|
||||||
if "--verbose" in sys.argv:
|
if "--verbose" in sys.argv:
|
||||||
verbose = True
|
verbose = True
|
||||||
sys.argv.remove("--verbose")
|
sys.argv.remove("--verbose")
|
||||||
@@ -633,8 +635,8 @@ if __name__ == "__main__":
|
|||||||
manifest = read_manifest()
|
manifest = read_manifest()
|
||||||
validate_manifest(manifest)
|
validate_manifest(manifest)
|
||||||
all_platform_targets = manifest["target"]["platforms"].split(",")
|
all_platform_targets = manifest["target"]["platforms"].split(",")
|
||||||
# Update SDK cache (sdk.json)
|
# Update SDK cache (tool.json)
|
||||||
if should_update_sdk_json() and not update_sdk_json():
|
if should_update_tool_json() and not update_tool_json():
|
||||||
exit_with_error("Failed to retrieve SDK info")
|
exit_with_error("Failed to retrieve SDK info")
|
||||||
# Actions
|
# Actions
|
||||||
if action_arg == "build":
|
if action_arg == "build":
|
||||||
@@ -644,7 +646,8 @@ if __name__ == "__main__":
|
|||||||
platform = None
|
platform = None
|
||||||
if len(sys.argv) > 2:
|
if len(sys.argv) > 2:
|
||||||
platform = sys.argv[2]
|
platform = sys.argv[2]
|
||||||
build_action(manifest, platform)
|
if not build_action(manifest, platform):
|
||||||
|
sys.exit(1)
|
||||||
elif action_arg == "clean":
|
elif action_arg == "clean":
|
||||||
clean_action()
|
clean_action()
|
||||||
elif action_arg == "clearcache":
|
elif action_arg == "clearcache":
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
[manifest]
|
[manifest]
|
||||||
version=0.1
|
version=0.1
|
||||||
[target]
|
[target]
|
||||||
sdk=0.6.0
|
sdk=0.7.0-dev
|
||||||
platforms=esp32,esp32s3
|
platforms=esp32,esp32s3,esp32c6,esp32p4
|
||||||
[app]
|
[app]
|
||||||
id=one.tactility.helloworld
|
id=one.tactility.helloworld
|
||||||
versionName=0.2.0
|
versionName=0.3.0
|
||||||
versionCode=2
|
versionCode=3
|
||||||
name=Hello World
|
name=Hello World
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import requests
|
|||||||
import tarfile
|
import tarfile
|
||||||
|
|
||||||
ttbuild_path = ".tactility"
|
ttbuild_path = ".tactility"
|
||||||
ttbuild_version = "2.5.0"
|
ttbuild_version = "3.1.0"
|
||||||
ttbuild_cdn = "https://cdn.tactility.one"
|
ttbuild_cdn = "https://cdn.tactility.one"
|
||||||
ttbuild_sdk_json_validity = 3600 # seconds
|
ttbuild_sdk_json_validity = 3600 # seconds
|
||||||
ttport = 6666
|
ttport = 6666
|
||||||
@@ -20,20 +20,12 @@ verbose = False
|
|||||||
use_local_sdk = False
|
use_local_sdk = False
|
||||||
local_base_path = None
|
local_base_path = None
|
||||||
|
|
||||||
if sys.platform == "win32":
|
shell_color_red = "\033[91m"
|
||||||
shell_color_red = "\033[91m"
|
shell_color_orange = "\033[93m"
|
||||||
shell_color_orange = "\033[93m"
|
shell_color_green = "\033[32m"
|
||||||
shell_color_green = "\033[32m"
|
shell_color_purple = "\033[35m"
|
||||||
shell_color_purple = "\033[35m"
|
shell_color_cyan = "\033[36m"
|
||||||
shell_color_cyan = "\033[36m"
|
shell_color_reset = "\033[m"
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
else:
|
|
||||||
shell_color_red = "\033[91m"
|
|
||||||
shell_color_orange = "\033[93m"
|
|
||||||
shell_color_green = "\033[32m"
|
|
||||||
shell_color_purple = "\033[35m"
|
|
||||||
shell_color_cyan = "\033[36m"
|
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
|
|
||||||
def print_help():
|
def print_help():
|
||||||
print("Usage: python tactility.py [action] [options]")
|
print("Usage: python tactility.py [action] [options]")
|
||||||
@@ -115,9 +107,9 @@ def read_properties_file(path):
|
|||||||
#region SDK helpers
|
#region SDK helpers
|
||||||
|
|
||||||
def read_sdk_json():
|
def read_sdk_json():
|
||||||
json_file_path = os.path.join(ttbuild_path, "sdk.json")
|
json_file_path = os.path.join(ttbuild_path, "tool.json")
|
||||||
json_file = open(json_file_path)
|
with open(json_file_path) as json_file:
|
||||||
return json.load(json_file)
|
return json.load(json_file)
|
||||||
|
|
||||||
def get_sdk_dir(version, platform):
|
def get_sdk_dir(version, platform):
|
||||||
global use_local_sdk, local_base_path
|
global use_local_sdk, local_base_path
|
||||||
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
|
|||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
||||||
|
|
||||||
def get_sdk_url(version, platform):
|
def get_sdk_url(version, file):
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
|
return f"{ttbuild_cdn}/sdk/{version}/{file}"
|
||||||
|
|
||||||
def sdk_exists(version, platform):
|
def sdk_exists(version, platform):
|
||||||
sdk_dir = get_sdk_dir(version, platform)
|
sdk_dir = get_sdk_dir(version, platform)
|
||||||
return os.path.isdir(sdk_dir)
|
return os.path.isdir(sdk_dir)
|
||||||
|
|
||||||
def should_update_sdk_json():
|
def should_update_tool_json():
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
if os.path.exists(json_filepath):
|
if os.path.exists(json_filepath):
|
||||||
json_modification_time = os.path.getmtime(json_filepath)
|
json_modification_time = os.path.getmtime(json_filepath)
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@@ -168,10 +160,10 @@ def should_update_sdk_json():
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_sdk_json():
|
def update_tool_json():
|
||||||
global ttbuild_cdn, ttbuild_path
|
global ttbuild_cdn, ttbuild_path
|
||||||
json_url = f"{ttbuild_cdn}/sdk.json"
|
json_url = f"{ttbuild_cdn}/sdk/tool.json"
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
return download_file(json_url, json_filepath)
|
return download_file(json_url, json_filepath)
|
||||||
|
|
||||||
def should_fetch_sdkconfig_files(platform_targets):
|
def should_fetch_sdkconfig_files(platform_targets):
|
||||||
@@ -206,16 +198,6 @@ def validate_environment():
|
|||||||
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
||||||
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
||||||
|
|
||||||
def validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
|
|
||||||
version_map = sdk_json["versions"]
|
|
||||||
if not sdk_version in version_map:
|
|
||||||
exit_with_error(f"Version not found: {sdk_version}")
|
|
||||||
version_data = version_map[sdk_version]
|
|
||||||
available_platforms = version_data["platforms"]
|
|
||||||
for desired_platform in platforms_to_build:
|
|
||||||
if not desired_platform in available_platforms:
|
|
||||||
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
|
|
||||||
|
|
||||||
def validate_self(sdk_json):
|
def validate_self(sdk_json):
|
||||||
if not "toolVersion" in sdk_json:
|
if not "toolVersion" in sdk_json:
|
||||||
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
||||||
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
|
|||||||
def sdk_download(version, platform):
|
def sdk_download(version, platform):
|
||||||
sdk_root_dir = get_sdk_root_dir(version, platform)
|
sdk_root_dir = get_sdk_root_dir(version, platform)
|
||||||
os.makedirs(sdk_root_dir, exist_ok=True)
|
os.makedirs(sdk_root_dir, exist_ok=True)
|
||||||
sdk_url = get_sdk_url(version, platform)
|
sdk_index_url = get_sdk_url(version, "index.json")
|
||||||
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
|
||||||
print(f"Downloading SDK version {version} for {platform}")
|
print(f"Downloading SDK version {version} for {platform}")
|
||||||
if download_file(sdk_url, filepath):
|
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
|
||||||
with zipfile.ZipFile(filepath, "r") as zip_ref:
|
if verbose:
|
||||||
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
|
||||||
return True
|
if not download_file(sdk_index_url, sdk_index_filepath):
|
||||||
else:
|
# TODO: 404 check, print a more accurate error
|
||||||
|
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
|
||||||
return False
|
return False
|
||||||
|
with open(sdk_index_filepath) as sdk_index_json_file:
|
||||||
|
sdk_index_json = json.load(sdk_index_json_file)
|
||||||
|
sdk_platforms = sdk_index_json["platforms"]
|
||||||
|
if platform not in sdk_platforms:
|
||||||
|
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
|
||||||
|
return False
|
||||||
|
sdk_platform_file = sdk_platforms[platform]
|
||||||
|
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
|
||||||
|
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
||||||
|
if verbose:
|
||||||
|
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
|
||||||
|
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
return False
|
||||||
|
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
|
||||||
|
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
||||||
|
return True
|
||||||
|
|
||||||
def sdk_download_all(version, platforms):
|
def sdk_download_all(version, platforms):
|
||||||
for platform in platforms:
|
for platform in platforms:
|
||||||
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "build"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "elf"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
print_status_success(f"Building {platform} ELF")
|
print_status_success(f"Building {platform} ELF")
|
||||||
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
|
|||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
sdk_json = read_sdk_json()
|
sdk_json = read_sdk_json()
|
||||||
validate_self(sdk_json)
|
validate_self(sdk_json)
|
||||||
if not "versions" in sdk_json:
|
|
||||||
exit_with_error("Version data not found in sdk.json")
|
|
||||||
# Build
|
# Build
|
||||||
sdk_version = manifest["target"]["sdk"]
|
sdk_version = manifest["target"]["sdk"]
|
||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build)
|
|
||||||
if not sdk_download_all(sdk_version, platforms_to_build):
|
if not sdk_download_all(sdk_version, platforms_to_build):
|
||||||
exit_with_error("Failed to download one or more SDKs")
|
exit_with_error("Failed to download one or more SDKs")
|
||||||
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
||||||
@@ -613,7 +615,7 @@ if __name__ == "__main__":
|
|||||||
# Argument validation
|
# Argument validation
|
||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 1:
|
||||||
print_help()
|
print_help()
|
||||||
sys.exit()
|
sys.exit(1)
|
||||||
if "--verbose" in sys.argv:
|
if "--verbose" in sys.argv:
|
||||||
verbose = True
|
verbose = True
|
||||||
sys.argv.remove("--verbose")
|
sys.argv.remove("--verbose")
|
||||||
@@ -633,8 +635,8 @@ if __name__ == "__main__":
|
|||||||
manifest = read_manifest()
|
manifest = read_manifest()
|
||||||
validate_manifest(manifest)
|
validate_manifest(manifest)
|
||||||
all_platform_targets = manifest["target"]["platforms"].split(",")
|
all_platform_targets = manifest["target"]["platforms"].split(",")
|
||||||
# Update SDK cache (sdk.json)
|
# Update SDK cache (tool.json)
|
||||||
if should_update_sdk_json() and not update_sdk_json():
|
if should_update_tool_json() and not update_tool_json():
|
||||||
exit_with_error("Failed to retrieve SDK info")
|
exit_with_error("Failed to retrieve SDK info")
|
||||||
# Actions
|
# Actions
|
||||||
if action_arg == "build":
|
if action_arg == "build":
|
||||||
@@ -644,7 +646,8 @@ if __name__ == "__main__":
|
|||||||
platform = None
|
platform = None
|
||||||
if len(sys.argv) > 2:
|
if len(sys.argv) > 2:
|
||||||
platform = sys.argv[2]
|
platform = sys.argv[2]
|
||||||
build_action(manifest, platform)
|
if not build_action(manifest, platform):
|
||||||
|
sys.exit(1)
|
||||||
elif action_arg == "clean":
|
elif action_arg == "clean":
|
||||||
clean_action()
|
clean_action()
|
||||||
elif action_arg == "clearcache":
|
elif action_arg == "clearcache":
|
||||||
|
|||||||
@@ -1,16 +1,11 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES
|
file(GLOB_RECURSE SOURCE_FILES
|
||||||
Source/*.c*
|
Source/*.c*
|
||||||
# Library source files must be included directly,
|
|
||||||
# because all regular dependencies get stripped by elf_loader's cmake script
|
|
||||||
../../../Libraries/Str/Source/*.c**
|
|
||||||
../../../Libraries/TactilityCpp/Source/*.c**
|
|
||||||
)
|
)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
# Library headers must be included directly,
|
# Library headers must be included directly,
|
||||||
# because all regular dependencies get stripped by elf_loader's cmake script
|
# because all regular dependencies get stripped by elf_loader's cmake script
|
||||||
INCLUDE_DIRS ../../../Libraries/Str/Include
|
|
||||||
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
|
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
|
||||||
REQUIRES TactilitySDK
|
REQUIRES TactilitySDK
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
#include <Str.h>
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
@@ -21,7 +20,7 @@ class ConnectView final : public View {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
typedef std::function<void(std::unique_ptr<Uart>)> OnConnectedFunction;
|
typedef std::function<void(std::unique_ptr<Uart>)> OnConnectedFunction;
|
||||||
std::vector<Str> uartNames;
|
std::vector<std::string> uartNames;
|
||||||
Preferences preferences = Preferences("SerialConsole");
|
Preferences preferences = Preferences("SerialConsole");
|
||||||
LvglLock lvglLock;
|
LvglLock lvglLock;
|
||||||
|
|
||||||
@@ -31,8 +30,8 @@ private:
|
|||||||
lv_obj_t* busDropdown = nullptr;
|
lv_obj_t* busDropdown = nullptr;
|
||||||
lv_obj_t* speedTextarea = nullptr;
|
lv_obj_t* speedTextarea = nullptr;
|
||||||
|
|
||||||
Str join(const std::vector<Str>& list) {
|
std::string join(const std::vector<std::string>& list) {
|
||||||
Str output;
|
std::string output;
|
||||||
for (int i = list.size() - 1; i >= 0; i--) {
|
for (int i = list.size() - 1; i >= 0; i--) {
|
||||||
output.append(list[i].c_str());
|
output.append(list[i].c_str());
|
||||||
if (i < list.size() - 1) {
|
if (i < list.size() - 1) {
|
||||||
|
|||||||
@@ -3,16 +3,15 @@
|
|||||||
#include "View.h"
|
#include "View.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
|
|
||||||
#include <Str.h>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <lvgl.h>
|
#include <lvgl.h>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#include <tt_lvgl.h>
|
#include <tt_lvgl.h>
|
||||||
#include <tt_thread.h>
|
|
||||||
|
|
||||||
#include <TactilityCpp/Mutex.h>
|
#include <Tactility/RecursiveMutex.h>
|
||||||
#include <TactilityCpp/Thread.h>
|
#include <Tactility/Thread.h>
|
||||||
#include <TactilityCpp/LvglLock.h>
|
#include <TactilityCpp/LvglLock.h>
|
||||||
|
|
||||||
constexpr size_t receiveBufferSize = 512;
|
constexpr size_t receiveBufferSize = 512;
|
||||||
@@ -26,15 +25,15 @@ class ConsoleView final : public View {
|
|||||||
lv_obj_t* _Nullable logTextarea = nullptr;
|
lv_obj_t* _Nullable logTextarea = nullptr;
|
||||||
lv_obj_t* _Nullable inputTextarea = nullptr;
|
lv_obj_t* _Nullable inputTextarea = nullptr;
|
||||||
std::shared_ptr<Uart> _Nullable uart = nullptr;
|
std::shared_ptr<Uart> _Nullable uart = nullptr;
|
||||||
std::shared_ptr<Thread> uartThread _Nullable = nullptr;
|
std::unique_ptr<tt::Thread> uartThread _Nullable = nullptr;
|
||||||
bool uartThreadInterrupted = false;
|
bool uartThreadInterrupted = false;
|
||||||
std::shared_ptr<Thread> viewThread _Nullable = nullptr;
|
std::unique_ptr<tt::Thread> viewThread _Nullable = nullptr;
|
||||||
bool viewThreadInterrupted = false;
|
bool viewThreadInterrupted = false;
|
||||||
Mutex mutex = Mutex(MutexTypeRecursive);
|
tt::RecursiveMutex mutex;
|
||||||
uint8_t receiveBuffer[receiveBufferSize];
|
uint8_t receiveBuffer[receiveBufferSize];
|
||||||
uint8_t renderBuffer[renderBufferSize];
|
uint8_t renderBuffer[renderBufferSize];
|
||||||
size_t receiveBufferPosition = 0;
|
size_t receiveBufferPosition = 0;
|
||||||
Str terminatorString = "\n";
|
std::string terminatorString = "\n";
|
||||||
|
|
||||||
LvglLock lvglLock;
|
LvglLock lvglLock;
|
||||||
|
|
||||||
@@ -51,11 +50,6 @@ class ConsoleView final : public View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void updateViews() {
|
void updateViews() {
|
||||||
auto scoped_lvgl_lock = lvglLock.asScopedLock();
|
|
||||||
if (!scoped_lvgl_lock.lock()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (parent == nullptr) {
|
if (parent == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -73,38 +67,35 @@ class ConsoleView final : public View {
|
|||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
}
|
}
|
||||||
|
|
||||||
tt_lvgl_lock(TT_MAX_TICKS);
|
if (lvglLock.lock()) {
|
||||||
lv_textarea_set_text(logTextarea, (const char*)renderBuffer);
|
lv_textarea_set_text(logTextarea, (const char*)renderBuffer);
|
||||||
tt_lvgl_unlock();
|
lvglLock.unlock();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t viewThreadMain() {
|
int32_t viewThreadMain() {
|
||||||
while (!isViewThreadInterrupted()) {
|
while (!isViewThreadInterrupted()) {
|
||||||
auto start_time = tt_kernel_get_ticks();
|
auto start_time = tt::kernel::getTicks();
|
||||||
|
|
||||||
updateViews();
|
updateViews();
|
||||||
|
|
||||||
auto end_time = tt_kernel_get_ticks();
|
auto end_time = tt::kernel::getTicks();
|
||||||
auto time_diff = end_time - start_time;
|
auto time_diff = end_time - start_time;
|
||||||
if (time_diff < 500U) {
|
auto target_delay = tt::kernel::millisToTicks(500U);
|
||||||
tt_kernel_delay_ticks((500U - time_diff) / portTICK_PERIOD_MS);
|
if (time_diff < target_delay) {
|
||||||
|
tt::kernel::delayTicks(target_delay - time_diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t viewThreadMainStatic(void* context) {
|
|
||||||
auto* self = static_cast<ConsoleView*>(context);
|
|
||||||
return self->viewThreadMain();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t uartThreadMain() {
|
int32_t uartThreadMain() {
|
||||||
char byte;
|
char byte;
|
||||||
|
|
||||||
while (!isUartThreadInterrupted()) {
|
while (!isUartThreadInterrupted()) {
|
||||||
assert(uart != nullptr);
|
assert(uart != nullptr);
|
||||||
bool success = uart->readByte(&byte, 50 / portTICK_PERIOD_MS);
|
bool success = uart->readByte(&byte, tt::kernel::millisToTicks(50));
|
||||||
|
|
||||||
// Thread might've been interrupted in the meanwhile
|
// Thread might've been interrupted in the meanwhile
|
||||||
if (isUartThreadInterrupted()) {
|
if (isUartThreadInterrupted()) {
|
||||||
@@ -125,11 +116,6 @@ class ConsoleView final : public View {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int32_t uartThreadMainStatic(void* view) {
|
|
||||||
auto* self = static_cast<ConsoleView*>(view);
|
|
||||||
return self->uartThreadMain();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void onSendClickedCallback(lv_event_t* event) {
|
static void onSendClickedCallback(lv_event_t* event) {
|
||||||
auto* view = (ConsoleView*)lv_event_get_user_data(event);
|
auto* view = (ConsoleView*)lv_event_get_user_data(event);
|
||||||
view->onSendClicked();
|
view->onSendClicked();
|
||||||
@@ -156,9 +142,9 @@ class ConsoleView final : public View {
|
|||||||
|
|
||||||
void onSendClicked() {
|
void onSendClicked() {
|
||||||
mutex.lock();
|
mutex.lock();
|
||||||
Str input_text = lv_textarea_get_text(inputTextarea);
|
std::string input_text = lv_textarea_get_text(inputTextarea);
|
||||||
Str to_send;
|
std::string to_send;
|
||||||
to_send.appendf("%s%s", input_text.c_str(), terminatorString.c_str());
|
to_send.append(input_text + terminatorString);
|
||||||
mutex.unlock();
|
mutex.unlock();
|
||||||
|
|
||||||
if (uart != nullptr) {
|
if (uart != nullptr) {
|
||||||
@@ -181,13 +167,12 @@ public:
|
|||||||
uart = std::move(newUart);
|
uart = std::move(newUart);
|
||||||
|
|
||||||
uartThreadInterrupted = false;
|
uartThreadInterrupted = false;
|
||||||
uartThread = std::make_unique<Thread>(
|
uartThread = std::make_unique<tt::Thread>(
|
||||||
"SerConsUart",
|
"SerConsUart",
|
||||||
4096,
|
4096,
|
||||||
uartThreadMainStatic,
|
[this] { return uartThreadMain(); }
|
||||||
this
|
|
||||||
);
|
);
|
||||||
uartThread->setPriority(ThreadPriorityHigh);
|
uartThread->setPriority(tt::Thread::Priority::High);
|
||||||
uartThread->start();
|
uartThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,13 +213,12 @@ public:
|
|||||||
lv_obj_add_event_cb(button, onSendClickedCallback, LV_EVENT_SHORT_CLICKED, this);
|
lv_obj_add_event_cb(button, onSendClickedCallback, LV_EVENT_SHORT_CLICKED, this);
|
||||||
|
|
||||||
viewThreadInterrupted = false;
|
viewThreadInterrupted = false;
|
||||||
viewThread = std::make_unique<Thread>(
|
viewThread = std::make_unique<tt::Thread>(
|
||||||
"SerConsView",
|
"SerConsView",
|
||||||
4096,
|
4096,
|
||||||
viewThreadMainStatic,
|
[this] { return viewThreadMain(); }
|
||||||
this
|
|
||||||
);
|
);
|
||||||
viewThread->setPriority(ThreadPriorityHigher);
|
viewThread->setPriority(tt::Thread::Priority::Higher);
|
||||||
viewThread->start();
|
viewThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +233,7 @@ public:
|
|||||||
// Unlock so thread can lock
|
// Unlock so thread can lock
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
if (old_uart_thread->getState() != ThreadStateStopped) {
|
if (old_uart_thread->getState() != tt::Thread::State::Stopped) {
|
||||||
// Wait for thread to finish
|
// Wait for thread to finish
|
||||||
old_uart_thread->join();
|
old_uart_thread->join();
|
||||||
}
|
}
|
||||||
@@ -267,7 +251,7 @@ public:
|
|||||||
// Unlock so thread can lock
|
// Unlock so thread can lock
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
if (old_view_thread->getState() != ThreadStateStopped) {
|
if (old_view_thread->getState() != tt::Thread::State::Stopped) {
|
||||||
// Wait for thread to finish
|
// Wait for thread to finish
|
||||||
old_view_thread->join();
|
old_view_thread->join();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
[manifest]
|
[manifest]
|
||||||
version=0.1
|
version=0.1
|
||||||
[target]
|
[target]
|
||||||
sdk=0.6.0
|
sdk=0.7.0-dev
|
||||||
platforms=esp32,esp32s3
|
platforms=esp32,esp32s3,esp32c6,esp32p4
|
||||||
[app]
|
[app]
|
||||||
id=one.tactility.serialconsole
|
id=one.tactility.serialconsole
|
||||||
versionName=0.2.0
|
versionName=0.3.0
|
||||||
versionCode=2
|
versionCode=3
|
||||||
name=Serial Console
|
name=Serial Console
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import requests
|
|||||||
import tarfile
|
import tarfile
|
||||||
|
|
||||||
ttbuild_path = ".tactility"
|
ttbuild_path = ".tactility"
|
||||||
ttbuild_version = "2.5.0"
|
ttbuild_version = "3.1.0"
|
||||||
ttbuild_cdn = "https://cdn.tactility.one"
|
ttbuild_cdn = "https://cdn.tactility.one"
|
||||||
ttbuild_sdk_json_validity = 3600 # seconds
|
ttbuild_sdk_json_validity = 3600 # seconds
|
||||||
ttport = 6666
|
ttport = 6666
|
||||||
@@ -20,20 +20,12 @@ verbose = False
|
|||||||
use_local_sdk = False
|
use_local_sdk = False
|
||||||
local_base_path = None
|
local_base_path = None
|
||||||
|
|
||||||
if sys.platform == "win32":
|
shell_color_red = "\033[91m"
|
||||||
shell_color_red = "\033[91m"
|
shell_color_orange = "\033[93m"
|
||||||
shell_color_orange = "\033[93m"
|
shell_color_green = "\033[32m"
|
||||||
shell_color_green = "\033[32m"
|
shell_color_purple = "\033[35m"
|
||||||
shell_color_purple = "\033[35m"
|
shell_color_cyan = "\033[36m"
|
||||||
shell_color_cyan = "\033[36m"
|
shell_color_reset = "\033[m"
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
else:
|
|
||||||
shell_color_red = "\033[91m"
|
|
||||||
shell_color_orange = "\033[93m"
|
|
||||||
shell_color_green = "\033[32m"
|
|
||||||
shell_color_purple = "\033[35m"
|
|
||||||
shell_color_cyan = "\033[36m"
|
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
|
|
||||||
def print_help():
|
def print_help():
|
||||||
print("Usage: python tactility.py [action] [options]")
|
print("Usage: python tactility.py [action] [options]")
|
||||||
@@ -115,9 +107,9 @@ def read_properties_file(path):
|
|||||||
#region SDK helpers
|
#region SDK helpers
|
||||||
|
|
||||||
def read_sdk_json():
|
def read_sdk_json():
|
||||||
json_file_path = os.path.join(ttbuild_path, "sdk.json")
|
json_file_path = os.path.join(ttbuild_path, "tool.json")
|
||||||
json_file = open(json_file_path)
|
with open(json_file_path) as json_file:
|
||||||
return json.load(json_file)
|
return json.load(json_file)
|
||||||
|
|
||||||
def get_sdk_dir(version, platform):
|
def get_sdk_dir(version, platform):
|
||||||
global use_local_sdk, local_base_path
|
global use_local_sdk, local_base_path
|
||||||
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
|
|||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
||||||
|
|
||||||
def get_sdk_url(version, platform):
|
def get_sdk_url(version, file):
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
|
return f"{ttbuild_cdn}/sdk/{version}/{file}"
|
||||||
|
|
||||||
def sdk_exists(version, platform):
|
def sdk_exists(version, platform):
|
||||||
sdk_dir = get_sdk_dir(version, platform)
|
sdk_dir = get_sdk_dir(version, platform)
|
||||||
return os.path.isdir(sdk_dir)
|
return os.path.isdir(sdk_dir)
|
||||||
|
|
||||||
def should_update_sdk_json():
|
def should_update_tool_json():
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
if os.path.exists(json_filepath):
|
if os.path.exists(json_filepath):
|
||||||
json_modification_time = os.path.getmtime(json_filepath)
|
json_modification_time = os.path.getmtime(json_filepath)
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@@ -168,10 +160,10 @@ def should_update_sdk_json():
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_sdk_json():
|
def update_tool_json():
|
||||||
global ttbuild_cdn, ttbuild_path
|
global ttbuild_cdn, ttbuild_path
|
||||||
json_url = f"{ttbuild_cdn}/sdk.json"
|
json_url = f"{ttbuild_cdn}/sdk/tool.json"
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
return download_file(json_url, json_filepath)
|
return download_file(json_url, json_filepath)
|
||||||
|
|
||||||
def should_fetch_sdkconfig_files(platform_targets):
|
def should_fetch_sdkconfig_files(platform_targets):
|
||||||
@@ -206,16 +198,6 @@ def validate_environment():
|
|||||||
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
||||||
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
||||||
|
|
||||||
def validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
|
|
||||||
version_map = sdk_json["versions"]
|
|
||||||
if not sdk_version in version_map:
|
|
||||||
exit_with_error(f"Version not found: {sdk_version}")
|
|
||||||
version_data = version_map[sdk_version]
|
|
||||||
available_platforms = version_data["platforms"]
|
|
||||||
for desired_platform in platforms_to_build:
|
|
||||||
if not desired_platform in available_platforms:
|
|
||||||
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
|
|
||||||
|
|
||||||
def validate_self(sdk_json):
|
def validate_self(sdk_json):
|
||||||
if not "toolVersion" in sdk_json:
|
if not "toolVersion" in sdk_json:
|
||||||
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
||||||
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
|
|||||||
def sdk_download(version, platform):
|
def sdk_download(version, platform):
|
||||||
sdk_root_dir = get_sdk_root_dir(version, platform)
|
sdk_root_dir = get_sdk_root_dir(version, platform)
|
||||||
os.makedirs(sdk_root_dir, exist_ok=True)
|
os.makedirs(sdk_root_dir, exist_ok=True)
|
||||||
sdk_url = get_sdk_url(version, platform)
|
sdk_index_url = get_sdk_url(version, "index.json")
|
||||||
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
|
||||||
print(f"Downloading SDK version {version} for {platform}")
|
print(f"Downloading SDK version {version} for {platform}")
|
||||||
if download_file(sdk_url, filepath):
|
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
|
||||||
with zipfile.ZipFile(filepath, "r") as zip_ref:
|
if verbose:
|
||||||
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
|
||||||
return True
|
if not download_file(sdk_index_url, sdk_index_filepath):
|
||||||
else:
|
# TODO: 404 check, print a more accurate error
|
||||||
|
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
|
||||||
return False
|
return False
|
||||||
|
with open(sdk_index_filepath) as sdk_index_json_file:
|
||||||
|
sdk_index_json = json.load(sdk_index_json_file)
|
||||||
|
sdk_platforms = sdk_index_json["platforms"]
|
||||||
|
if platform not in sdk_platforms:
|
||||||
|
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
|
||||||
|
return False
|
||||||
|
sdk_platform_file = sdk_platforms[platform]
|
||||||
|
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
|
||||||
|
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
||||||
|
if verbose:
|
||||||
|
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
|
||||||
|
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
return False
|
||||||
|
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
|
||||||
|
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
||||||
|
return True
|
||||||
|
|
||||||
def sdk_download_all(version, platforms):
|
def sdk_download_all(version, platforms):
|
||||||
for platform in platforms:
|
for platform in platforms:
|
||||||
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "build"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "elf"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
print_status_success(f"Building {platform} ELF")
|
print_status_success(f"Building {platform} ELF")
|
||||||
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
|
|||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
sdk_json = read_sdk_json()
|
sdk_json = read_sdk_json()
|
||||||
validate_self(sdk_json)
|
validate_self(sdk_json)
|
||||||
if not "versions" in sdk_json:
|
|
||||||
exit_with_error("Version data not found in sdk.json")
|
|
||||||
# Build
|
# Build
|
||||||
sdk_version = manifest["target"]["sdk"]
|
sdk_version = manifest["target"]["sdk"]
|
||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build)
|
|
||||||
if not sdk_download_all(sdk_version, platforms_to_build):
|
if not sdk_download_all(sdk_version, platforms_to_build):
|
||||||
exit_with_error("Failed to download one or more SDKs")
|
exit_with_error("Failed to download one or more SDKs")
|
||||||
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
||||||
@@ -613,7 +615,7 @@ if __name__ == "__main__":
|
|||||||
# Argument validation
|
# Argument validation
|
||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 1:
|
||||||
print_help()
|
print_help()
|
||||||
sys.exit()
|
sys.exit(1)
|
||||||
if "--verbose" in sys.argv:
|
if "--verbose" in sys.argv:
|
||||||
verbose = True
|
verbose = True
|
||||||
sys.argv.remove("--verbose")
|
sys.argv.remove("--verbose")
|
||||||
@@ -633,8 +635,8 @@ if __name__ == "__main__":
|
|||||||
manifest = read_manifest()
|
manifest = read_manifest()
|
||||||
validate_manifest(manifest)
|
validate_manifest(manifest)
|
||||||
all_platform_targets = manifest["target"]["platforms"].split(",")
|
all_platform_targets = manifest["target"]["platforms"].split(",")
|
||||||
# Update SDK cache (sdk.json)
|
# Update SDK cache (tool.json)
|
||||||
if should_update_sdk_json() and not update_sdk_json():
|
if should_update_tool_json() and not update_tool_json():
|
||||||
exit_with_error("Failed to retrieve SDK info")
|
exit_with_error("Failed to retrieve SDK info")
|
||||||
# Actions
|
# Actions
|
||||||
if action_arg == "build":
|
if action_arg == "build":
|
||||||
@@ -644,7 +646,8 @@ if __name__ == "__main__":
|
|||||||
platform = None
|
platform = None
|
||||||
if len(sys.argv) > 2:
|
if len(sys.argv) > 2:
|
||||||
platform = sys.argv[2]
|
platform = sys.argv[2]
|
||||||
build_action(manifest, platform)
|
if not build_action(manifest, platform):
|
||||||
|
sys.exit(1)
|
||||||
elif action_arg == "clean":
|
elif action_arg == "clean":
|
||||||
clean_action()
|
clean_action()
|
||||||
elif action_arg == "clearcache":
|
elif action_arg == "clearcache":
|
||||||
|
|||||||
@@ -1,15 +1,11 @@
|
|||||||
file(GLOB_RECURSE SOURCE_FILES
|
file(GLOB_RECURSE SOURCE_FILES
|
||||||
Source/*.c*
|
Source/*.c*
|
||||||
# Library source files must be included directly,
|
|
||||||
# because all regular dependencies get stripped by elf_loader's cmake script
|
|
||||||
../../../Libraries/Str/Source/*.c**
|
|
||||||
)
|
)
|
||||||
|
|
||||||
idf_component_register(
|
idf_component_register(
|
||||||
SRCS ${SOURCE_FILES}
|
SRCS ${SOURCE_FILES}
|
||||||
# Library headers must be included directly,
|
# Library headers must be included directly,
|
||||||
# because all regular dependencies get stripped by elf_loader's cmake script
|
# because all regular dependencies get stripped by elf_loader's cmake script
|
||||||
INCLUDE_DIRS ../../../Libraries/Str/Include
|
|
||||||
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
|
INCLUDE_DIRS ../../../Libraries/TactilityCpp/Include
|
||||||
REQUIRES TactilitySDK
|
REQUIRES TactilitySDK
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
[manifest]
|
[manifest]
|
||||||
version=0.1
|
version=0.1
|
||||||
[target]
|
[target]
|
||||||
sdk=0.7.0-SNAPSHOT2
|
sdk=0.7.0-dev
|
||||||
platforms=esp32,esp32s3
|
platforms=esp32,esp32s3,esp32c6,esp32p4
|
||||||
[app]
|
[app]
|
||||||
id=one.tactility.twoeleven
|
id=one.tactility.twoeleven
|
||||||
versionName=0.2.0
|
versionName=0.3.0
|
||||||
versionCode=2
|
versionCode=3
|
||||||
name=2048
|
name=2048
|
||||||
description=A fun, customizable 2048 sliding tile game for tactility!\nSlide tiles to combine numbers and reach 2048.\nChoose grid sizes: 3x3 (easy), 4x4 (classic), 5x5, or 6x6 (expert).
|
description=A fun, customizable 2048 sliding tile game for tactility!\nSlide tiles to combine numbers and reach 2048.\nChoose grid sizes: 3x3 (easy), 4x4 (classic), 5x5, or 6x6 (expert).
|
||||||
|
|||||||
+54
-51
@@ -12,7 +12,7 @@ import requests
|
|||||||
import tarfile
|
import tarfile
|
||||||
|
|
||||||
ttbuild_path = ".tactility"
|
ttbuild_path = ".tactility"
|
||||||
ttbuild_version = "2.5.0"
|
ttbuild_version = "3.1.0"
|
||||||
ttbuild_cdn = "https://cdn.tactility.one"
|
ttbuild_cdn = "https://cdn.tactility.one"
|
||||||
ttbuild_sdk_json_validity = 3600 # seconds
|
ttbuild_sdk_json_validity = 3600 # seconds
|
||||||
ttport = 6666
|
ttport = 6666
|
||||||
@@ -20,20 +20,12 @@ verbose = False
|
|||||||
use_local_sdk = False
|
use_local_sdk = False
|
||||||
local_base_path = None
|
local_base_path = None
|
||||||
|
|
||||||
if sys.platform == "win32":
|
shell_color_red = "\033[91m"
|
||||||
shell_color_red = "\033[91m"
|
shell_color_orange = "\033[93m"
|
||||||
shell_color_orange = "\033[93m"
|
shell_color_green = "\033[32m"
|
||||||
shell_color_green = "\033[32m"
|
shell_color_purple = "\033[35m"
|
||||||
shell_color_purple = "\033[35m"
|
shell_color_cyan = "\033[36m"
|
||||||
shell_color_cyan = "\033[36m"
|
shell_color_reset = "\033[m"
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
else:
|
|
||||||
shell_color_red = "\033[91m"
|
|
||||||
shell_color_orange = "\033[93m"
|
|
||||||
shell_color_green = "\033[32m"
|
|
||||||
shell_color_purple = "\033[35m"
|
|
||||||
shell_color_cyan = "\033[36m"
|
|
||||||
shell_color_reset = "\033[m"
|
|
||||||
|
|
||||||
def print_help():
|
def print_help():
|
||||||
print("Usage: python tactility.py [action] [options]")
|
print("Usage: python tactility.py [action] [options]")
|
||||||
@@ -115,9 +107,9 @@ def read_properties_file(path):
|
|||||||
#region SDK helpers
|
#region SDK helpers
|
||||||
|
|
||||||
def read_sdk_json():
|
def read_sdk_json():
|
||||||
json_file_path = os.path.join(ttbuild_path, "sdk.json")
|
json_file_path = os.path.join(ttbuild_path, "tool.json")
|
||||||
json_file = open(json_file_path)
|
with open(json_file_path) as json_file:
|
||||||
return json.load(json_file)
|
return json.load(json_file)
|
||||||
|
|
||||||
def get_sdk_dir(version, platform):
|
def get_sdk_dir(version, platform):
|
||||||
global use_local_sdk, local_base_path
|
global use_local_sdk, local_base_path
|
||||||
@@ -148,17 +140,17 @@ def get_sdk_root_dir(version, platform):
|
|||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
return os.path.join(ttbuild_path, f"{version}-{platform}")
|
||||||
|
|
||||||
def get_sdk_url(version, platform):
|
def get_sdk_url(version, file):
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
return f"{ttbuild_cdn}/TactilitySDK-{version}-{platform}.zip"
|
return f"{ttbuild_cdn}/sdk/{version}/{file}"
|
||||||
|
|
||||||
def sdk_exists(version, platform):
|
def sdk_exists(version, platform):
|
||||||
sdk_dir = get_sdk_dir(version, platform)
|
sdk_dir = get_sdk_dir(version, platform)
|
||||||
return os.path.isdir(sdk_dir)
|
return os.path.isdir(sdk_dir)
|
||||||
|
|
||||||
def should_update_sdk_json():
|
def should_update_tool_json():
|
||||||
global ttbuild_cdn
|
global ttbuild_cdn
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
if os.path.exists(json_filepath):
|
if os.path.exists(json_filepath):
|
||||||
json_modification_time = os.path.getmtime(json_filepath)
|
json_modification_time = os.path.getmtime(json_filepath)
|
||||||
now = time.time()
|
now = time.time()
|
||||||
@@ -168,10 +160,10 @@ def should_update_sdk_json():
|
|||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def update_sdk_json():
|
def update_tool_json():
|
||||||
global ttbuild_cdn, ttbuild_path
|
global ttbuild_cdn, ttbuild_path
|
||||||
json_url = f"{ttbuild_cdn}/sdk.json"
|
json_url = f"{ttbuild_cdn}/sdk/tool.json"
|
||||||
json_filepath = os.path.join(ttbuild_path, "sdk.json")
|
json_filepath = os.path.join(ttbuild_path, "tool.json")
|
||||||
return download_file(json_url, json_filepath)
|
return download_file(json_url, json_filepath)
|
||||||
|
|
||||||
def should_fetch_sdkconfig_files(platform_targets):
|
def should_fetch_sdkconfig_files(platform_targets):
|
||||||
@@ -206,16 +198,6 @@ def validate_environment():
|
|||||||
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
elif use_local_sdk == True and os.environ.get("TACTILITY_SDK_PATH") is None:
|
||||||
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
exit_with_error("local build was requested, but TACTILITY_SDK_PATH environment variable is not set.")
|
||||||
|
|
||||||
def validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build):
|
|
||||||
version_map = sdk_json["versions"]
|
|
||||||
if not sdk_version in version_map:
|
|
||||||
exit_with_error(f"Version not found: {sdk_version}")
|
|
||||||
version_data = version_map[sdk_version]
|
|
||||||
available_platforms = version_data["platforms"]
|
|
||||||
for desired_platform in platforms_to_build:
|
|
||||||
if not desired_platform in available_platforms:
|
|
||||||
exit_with_error(f"Platform {desired_platform} is not available. Available ones: {available_platforms}")
|
|
||||||
|
|
||||||
def validate_self(sdk_json):
|
def validate_self(sdk_json):
|
||||||
if not "toolVersion" in sdk_json:
|
if not "toolVersion" in sdk_json:
|
||||||
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
exit_with_error("Server returned invalid SDK data format (toolVersion not found)")
|
||||||
@@ -287,15 +269,32 @@ def get_manifest_target_platforms(manifest, requested_platform):
|
|||||||
def sdk_download(version, platform):
|
def sdk_download(version, platform):
|
||||||
sdk_root_dir = get_sdk_root_dir(version, platform)
|
sdk_root_dir = get_sdk_root_dir(version, platform)
|
||||||
os.makedirs(sdk_root_dir, exist_ok=True)
|
os.makedirs(sdk_root_dir, exist_ok=True)
|
||||||
sdk_url = get_sdk_url(version, platform)
|
sdk_index_url = get_sdk_url(version, "index.json")
|
||||||
filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
|
||||||
print(f"Downloading SDK version {version} for {platform}")
|
print(f"Downloading SDK version {version} for {platform}")
|
||||||
if download_file(sdk_url, filepath):
|
sdk_index_filepath = os.path.join(sdk_root_dir, "index.json")
|
||||||
with zipfile.ZipFile(filepath, "r") as zip_ref:
|
if verbose:
|
||||||
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
print(f"Downloading {sdk_index_url} to {sdk_index_filepath}")
|
||||||
return True
|
if not download_file(sdk_index_url, sdk_index_filepath):
|
||||||
else:
|
# TODO: 404 check, print a more accurate error
|
||||||
|
print_error(f"Failed to download SDK version {version}. Check your internet connection and make sure this release exists.")
|
||||||
return False
|
return False
|
||||||
|
with open(sdk_index_filepath) as sdk_index_json_file:
|
||||||
|
sdk_index_json = json.load(sdk_index_json_file)
|
||||||
|
sdk_platforms = sdk_index_json["platforms"]
|
||||||
|
if platform not in sdk_platforms:
|
||||||
|
print_error(f"Platform {platform} not found in {sdk_platforms} for version {version}")
|
||||||
|
return False
|
||||||
|
sdk_platform_file = sdk_platforms[platform]
|
||||||
|
sdk_zip_source_url = get_sdk_url(version, sdk_platform_file)
|
||||||
|
sdk_zip_target_filepath = os.path.join(sdk_root_dir, f"{version}-{platform}.zip")
|
||||||
|
if verbose:
|
||||||
|
print(f"Downloading {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
if not download_file(sdk_zip_source_url, sdk_zip_target_filepath):
|
||||||
|
print_error(f"Failed to download {sdk_zip_source_url} to {sdk_zip_target_filepath}")
|
||||||
|
return False
|
||||||
|
with zipfile.ZipFile(sdk_zip_target_filepath, "r") as zip_ref:
|
||||||
|
zip_ref.extractall(os.path.join(sdk_root_dir, "TactilitySDK"))
|
||||||
|
return True
|
||||||
|
|
||||||
def sdk_download_all(version, platforms):
|
def sdk_download_all(version, platforms):
|
||||||
for platform in platforms:
|
for platform in platforms:
|
||||||
@@ -378,7 +377,10 @@ def build_first(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "build"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "build"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
# The return code is never expected to be 0 due to a bug in the elf cmake script, but we keep it just in case
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
@@ -406,7 +408,10 @@ def build_consecutively(version, platform, skip_build):
|
|||||||
cmake_path = get_cmake_path(platform)
|
cmake_path = get_cmake_path(platform)
|
||||||
print_status_busy(f"Building {platform} ELF")
|
print_status_busy(f"Building {platform} ELF")
|
||||||
shell_needed = sys.platform == "win32"
|
shell_needed = sys.platform == "win32"
|
||||||
with subprocess.Popen(["idf.py", "-B", cmake_path, "elf"], stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
build_command = ["idf.py", "-B", cmake_path, "elf"]
|
||||||
|
if verbose:
|
||||||
|
print(f"Running command: {" ".join(build_command)}")
|
||||||
|
with subprocess.Popen(build_command, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=shell_needed) as process:
|
||||||
build_output = wait_for_process(process)
|
build_output = wait_for_process(process)
|
||||||
if process.returncode == 0:
|
if process.returncode == 0:
|
||||||
print_status_success(f"Building {platform} ELF")
|
print_status_success(f"Building {platform} ELF")
|
||||||
@@ -494,12 +499,9 @@ def build_action(manifest, platform_arg):
|
|||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
sdk_json = read_sdk_json()
|
sdk_json = read_sdk_json()
|
||||||
validate_self(sdk_json)
|
validate_self(sdk_json)
|
||||||
if not "versions" in sdk_json:
|
|
||||||
exit_with_error("Version data not found in sdk.json")
|
|
||||||
# Build
|
# Build
|
||||||
sdk_version = manifest["target"]["sdk"]
|
sdk_version = manifest["target"]["sdk"]
|
||||||
if not use_local_sdk:
|
if not use_local_sdk:
|
||||||
validate_version_and_platforms(sdk_json, sdk_version, platforms_to_build)
|
|
||||||
if not sdk_download_all(sdk_version, platforms_to_build):
|
if not sdk_download_all(sdk_version, platforms_to_build):
|
||||||
exit_with_error("Failed to download one or more SDKs")
|
exit_with_error("Failed to download one or more SDKs")
|
||||||
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
if not build_all(sdk_version, platforms_to_build, skip_build): # Environment validation
|
||||||
@@ -613,7 +615,7 @@ if __name__ == "__main__":
|
|||||||
# Argument validation
|
# Argument validation
|
||||||
if len(sys.argv) == 1:
|
if len(sys.argv) == 1:
|
||||||
print_help()
|
print_help()
|
||||||
sys.exit()
|
sys.exit(1)
|
||||||
if "--verbose" in sys.argv:
|
if "--verbose" in sys.argv:
|
||||||
verbose = True
|
verbose = True
|
||||||
sys.argv.remove("--verbose")
|
sys.argv.remove("--verbose")
|
||||||
@@ -633,8 +635,8 @@ if __name__ == "__main__":
|
|||||||
manifest = read_manifest()
|
manifest = read_manifest()
|
||||||
validate_manifest(manifest)
|
validate_manifest(manifest)
|
||||||
all_platform_targets = manifest["target"]["platforms"].split(",")
|
all_platform_targets = manifest["target"]["platforms"].split(",")
|
||||||
# Update SDK cache (sdk.json)
|
# Update SDK cache (tool.json)
|
||||||
if should_update_sdk_json() and not update_sdk_json():
|
if should_update_tool_json() and not update_tool_json():
|
||||||
exit_with_error("Failed to retrieve SDK info")
|
exit_with_error("Failed to retrieve SDK info")
|
||||||
# Actions
|
# Actions
|
||||||
if action_arg == "build":
|
if action_arg == "build":
|
||||||
@@ -644,7 +646,8 @@ if __name__ == "__main__":
|
|||||||
platform = None
|
platform = None
|
||||||
if len(sys.argv) > 2:
|
if len(sys.argv) > 2:
|
||||||
platform = sys.argv[2]
|
platform = sys.argv[2]
|
||||||
build_action(manifest, platform)
|
if not build_action(manifest, platform):
|
||||||
|
sys.exit(1)
|
||||||
elif action_arg == "clean":
|
elif action_arg == "clean":
|
||||||
clean_action()
|
clean_action()
|
||||||
elif action_arg == "clearcache":
|
elif action_arg == "clearcache":
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.20)
|
|
||||||
|
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
||||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
|
||||||
|
|
||||||
file(GLOB SOURCES "Source/*.c*")
|
|
||||||
file(GLOB HEADERS "Include/*.h*")
|
|
||||||
|
|
||||||
add_library(Str STATIC)
|
|
||||||
|
|
||||||
target_sources(Str PRIVATE ${SOURCES})
|
|
||||||
include_directories(Str "Include/")
|
|
||||||
target_include_directories(Str PUBLIC "Include/")
|
|
||||||
|
|
||||||
@@ -1,618 +0,0 @@
|
|||||||
// Str v0.33
|
|
||||||
// Simple C++ string type with an optional local buffer, by Omar Cornut
|
|
||||||
// https://github.com/ocornut/str
|
|
||||||
|
|
||||||
// LICENSE
|
|
||||||
// This software is in the public domain. Where that dedication is not
|
|
||||||
// recognized, you are granted a perpetual, irrevocable license to copy,
|
|
||||||
// distribute, and modify this file as you see fit.
|
|
||||||
|
|
||||||
// USAGE
|
|
||||||
// Include this file in whatever places need to refer to it.
|
|
||||||
// In ONE .cpp file, write '#define STR_IMPLEMENTATION' before the #include of this file.
|
|
||||||
// This expands out the actual implementation into that C/C++ file.
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
- This isn't a fully featured string class.
|
|
||||||
- It is a simple, bearable replacement to std::string that isn't heap abusive nor bloated (can actually be debugged by humans).
|
|
||||||
- String are mutable. We don't maintain size so length() is not-constant time.
|
|
||||||
- Maximum string size currently limited to 2 MB (we allocate 21 bits to hold capacity).
|
|
||||||
- Local buffer size is currently limited to 1023 bytes (we allocate 10 bits to hold local buffer size).
|
|
||||||
- In "non-owned" mode for literals/reference we don't do any tracking/counting of references.
|
|
||||||
- Overhead is 8-bytes in 32-bits, 16-bytes in 64-bits (12 + alignment).
|
|
||||||
- This code hasn't been tested very much. it is probably incomplete or broken. Made it for my own use.
|
|
||||||
|
|
||||||
The idea is that you can provide an arbitrary sized local buffer if you expect string to fit
|
|
||||||
most of the time, and then you avoid using costly heap.
|
|
||||||
|
|
||||||
No local buffer, always use heap, sizeof()==8~16 (depends if your pointers are 32-bits or 64-bits)
|
|
||||||
|
|
||||||
Str s = "hey";
|
|
||||||
|
|
||||||
With a local buffer of 16 bytes, sizeof() == 8~16 + 16 bytes.
|
|
||||||
|
|
||||||
Str16 s = "filename.h"; // copy into local buffer
|
|
||||||
Str16 s = "long_filename_not_very_long_but_longer_than_expected.h"; // use heap
|
|
||||||
|
|
||||||
With a local buffer of 256 bytes, sizeof() == 8~16 + 256 bytes.
|
|
||||||
|
|
||||||
Str256 s = "long_filename_not_very_long_but_longer_than_expected.h"; // copy into local buffer
|
|
||||||
|
|
||||||
Common sizes are defined at the bottom of Str.h, you may define your own.
|
|
||||||
|
|
||||||
Functions:
|
|
||||||
|
|
||||||
Str256 s;
|
|
||||||
s.set("hello sailor"); // set (copy)
|
|
||||||
s.setf("%s/%s.tmp", folder, filename); // set (w/format)
|
|
||||||
s.append("hello"); // append. cost a length() calculation!
|
|
||||||
s.appendf("hello %d", 42); // append (w/format). cost a length() calculation!
|
|
||||||
s.set_ref("Hey!"); // set (literal/reference, just copy pointer, no tracking)
|
|
||||||
|
|
||||||
Constructor helper for format string: add a trailing 'f' to the type. Underlying type is the same.
|
|
||||||
|
|
||||||
Str256f filename("%s/%s.tmp", folder, filename); // construct (w/format)
|
|
||||||
fopen(Str256f("%s/%s.tmp, folder, filename).c_str(), "rb"); // construct (w/format), use as function param, destruct
|
|
||||||
|
|
||||||
Constructor helper for reference/literal:
|
|
||||||
|
|
||||||
StrRef ref("literal"); // copy pointer, no allocation, no string copy
|
|
||||||
StrRef ref2(GetDebugName()); // copy pointer. no tracking of anything whatsoever, know what you are doing!
|
|
||||||
|
|
||||||
All StrXXX types derives from Str and instance hold the local buffer capacity. So you can pass e.g. Str256* to a function taking base type Str* and it will be functional.
|
|
||||||
|
|
||||||
void MyFunc(Str& s) { s = "Hello"; } // will use local buffer if available in Str instance
|
|
||||||
|
|
||||||
(Using a template e.g. Str<N> we could remove the LocalBufSize storage but it would make passing typed Str<> to functions tricky.
|
|
||||||
Instead we don't use template so you can pass them around as the base type Str*. Also, templates are ugly.)
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
CHANGELOG
|
|
||||||
0.33 - fixed capacity() return value to match standard. e.g. a Str256's capacity() now returns 255, not 256.
|
|
||||||
0.32 - added owned() accessor.
|
|
||||||
0.31 - fixed various warnings.
|
|
||||||
0.30 - turned into a single header file, removed Str.cpp.
|
|
||||||
0.29 - fixed bug when calling reserve on non-owned strings (ie. when using StrRef or set_ref), and fixed <string> include.
|
|
||||||
0.28 - breaking change: replaced Str32 by Str30 to avoid collision with Str32 from MacTypes.h .
|
|
||||||
0.27 - added STR_API and basic .natvis file.
|
|
||||||
0.26 - fixed set(cont char* src, const char* src_end) writing null terminator to the wrong position.
|
|
||||||
0.25 - allow set(const char* NULL) or operator= NULL to clear the string. note that set() from range or other types are not allowed.
|
|
||||||
0.24 - allow set_ref(const char* NULL) to clear the string. include fixes for linux.
|
|
||||||
0.23 - added append(char). added append_from(int idx, XXX) functions. fixed some compilers warnings.
|
|
||||||
0.22 - documentation improvements, comments. fixes for some compilers.
|
|
||||||
0.21 - added StrXXXf() constructor to construct directly from a format string.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
TODO
|
|
||||||
- Since we lose 4-bytes of padding on 64-bits architecture, perhaps just spread the header to 8-bytes and lift size limits?
|
|
||||||
- More functions/helpers.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef STR_INCLUDED
|
|
||||||
#define STR_INCLUDED
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
// CONFIGURATION
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifndef STR_MEMALLOC
|
|
||||||
#define STR_MEMALLOC malloc
|
|
||||||
#include <cstdio>
|
|
||||||
#endif
|
|
||||||
#ifndef STR_MEMFREE
|
|
||||||
#define STR_MEMFREE free
|
|
||||||
#include <cstdlib>
|
|
||||||
#endif
|
|
||||||
#ifndef STR_ASSERT
|
|
||||||
#define STR_ASSERT assert
|
|
||||||
#include <cassert>
|
|
||||||
#endif
|
|
||||||
#ifndef STR_API
|
|
||||||
#define STR_API
|
|
||||||
#endif
|
|
||||||
#include <cstdarg> // for va_list
|
|
||||||
#include <cstring> // for strlen, strcmp, memcpy, etc.
|
|
||||||
|
|
||||||
// Configuration: #define STR_DEFINE_STR32 1 to keep defining Str32/Str32f, but be warned: on macOS/iOS, MacTypes.h also defines a type named Str32.
|
|
||||||
#ifndef STR_DEFINE_STR32
|
|
||||||
#define STR_DEFINE_STR32 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
// HEADERS
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
|
|
||||||
// This is the base class that you can pass around
|
|
||||||
// Footprint is 8-bytes (32-bits arch) or 16-bytes (64-bits arch)
|
|
||||||
class STR_API Str
|
|
||||||
{
|
|
||||||
char* Data; // Point to LocalBuf() or heap allocated
|
|
||||||
int Capacity : 21; // Max 2 MB. Exclude zero terminator.
|
|
||||||
int LocalBufSize : 10; // Max 1023 bytes
|
|
||||||
unsigned int Owned : 1; // Set when we have ownership of the pointed data (most common, unless using set_ref() method or StrRef constructor)
|
|
||||||
|
|
||||||
public:
|
|
||||||
inline char* c_str() { return Data; }
|
|
||||||
inline const char* c_str() const { return Data; }
|
|
||||||
inline bool empty() const { return Data[0] == 0; }
|
|
||||||
inline int length() const { return (int)strlen(Data); } // by design, allow user to write into the buffer at any time
|
|
||||||
inline int capacity() const { return Capacity; }
|
|
||||||
inline bool owned() const { return Owned ? true : false; }
|
|
||||||
|
|
||||||
inline void set_ref(const char* src);
|
|
||||||
int setf(const char* fmt, ...);
|
|
||||||
int setfv(const char* fmt, va_list args);
|
|
||||||
int setf_nogrow(const char* fmt, ...);
|
|
||||||
int setfv_nogrow(const char* fmt, va_list args);
|
|
||||||
int append(char c);
|
|
||||||
int append(const char* s, const char* s_end = NULL);
|
|
||||||
int appendf(const char* fmt, ...);
|
|
||||||
int appendfv(const char* fmt, va_list args);
|
|
||||||
int append_from(int idx, char c);
|
|
||||||
int append_from(int idx, const char* s, const char* s_end = NULL); // If you know the string length or want to append from a certain point
|
|
||||||
int appendf_from(int idx, const char* fmt, ...);
|
|
||||||
int appendfv_from(int idx, const char* fmt, va_list args);
|
|
||||||
|
|
||||||
void clear();
|
|
||||||
void reserve(int cap);
|
|
||||||
void reserve_discard(int cap);
|
|
||||||
void shrink_to_fit();
|
|
||||||
|
|
||||||
inline char& operator[](size_t i) { return Data[i]; }
|
|
||||||
inline char operator[](size_t i) const { return Data[i]; }
|
|
||||||
//explicit operator const char*() const{ return Data; }
|
|
||||||
|
|
||||||
inline Str();
|
|
||||||
inline Str(const char* rhs);
|
|
||||||
inline void set(const char* src);
|
|
||||||
inline void set(const char* src, const char* src_end);
|
|
||||||
inline Str& operator=(const char* rhs) { set(rhs); return *this; }
|
|
||||||
inline bool operator==(const char* rhs) const { return strcmp(c_str(), rhs) == 0; }
|
|
||||||
|
|
||||||
inline Str(const Str& rhs);
|
|
||||||
inline void set(const Str& src);
|
|
||||||
inline void set(int count, char character);
|
|
||||||
inline Str& operator=(const Str& rhs) { set(rhs); return *this; }
|
|
||||||
inline bool operator==(const Str& rhs) const { return strcmp(c_str(), rhs.c_str()) == 0; }
|
|
||||||
|
|
||||||
inline Str(int amount, char character);
|
|
||||||
|
|
||||||
// Destructor for all variants
|
|
||||||
inline ~Str()
|
|
||||||
{
|
|
||||||
if (Owned && !is_using_local_buf())
|
|
||||||
STR_MEMFREE(Data);
|
|
||||||
}
|
|
||||||
|
|
||||||
static char* EmptyBuffer;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
inline char* local_buf() { return (char*)this + sizeof(Str); }
|
|
||||||
inline const char* local_buf() const { return (char*)this + sizeof(Str); }
|
|
||||||
inline bool is_using_local_buf() const { return Data == local_buf() && LocalBufSize != 0; }
|
|
||||||
|
|
||||||
// Constructor for StrXXX variants with local buffer
|
|
||||||
Str(unsigned short local_buf_size)
|
|
||||||
{
|
|
||||||
STR_ASSERT(local_buf_size < 1024);
|
|
||||||
Data = local_buf();
|
|
||||||
Data[0] = '\0';
|
|
||||||
Capacity = local_buf_size ? local_buf_size - 1 : 0;
|
|
||||||
LocalBufSize = local_buf_size;
|
|
||||||
Owned = 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
void Str::set(const char* src)
|
|
||||||
{
|
|
||||||
// We allow set(NULL) or via = operator to clear the string.
|
|
||||||
if (src == NULL)
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
int buf_len = (int)strlen(src);
|
|
||||||
if (Capacity < buf_len)
|
|
||||||
reserve_discard(buf_len);
|
|
||||||
memcpy(Data, src, (size_t)(buf_len + 1));
|
|
||||||
Owned = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Str::set(const char* src, const char* src_end)
|
|
||||||
{
|
|
||||||
STR_ASSERT(src != NULL && src_end >= src);
|
|
||||||
int buf_len = (int)(src_end - src);
|
|
||||||
if ((int)Capacity < buf_len)
|
|
||||||
reserve_discard(buf_len);
|
|
||||||
memcpy(Data, src, (size_t)buf_len);
|
|
||||||
Data[buf_len] = 0;
|
|
||||||
Owned = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Str::set(const Str& src)
|
|
||||||
{
|
|
||||||
int buf_len = (int)strlen(src.c_str());
|
|
||||||
if ((int)Capacity < buf_len)
|
|
||||||
reserve_discard(buf_len);
|
|
||||||
memcpy(Data, src.c_str(), (size_t)(buf_len + 1));
|
|
||||||
Owned = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Str::set(int count, char character) {
|
|
||||||
int buf_len = count + 1;
|
|
||||||
if ((int)Capacity < buf_len)
|
|
||||||
reserve_discard(buf_len);
|
|
||||||
memset(Data, character, count);
|
|
||||||
Data[count] = 0;
|
|
||||||
Owned = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void Str::set_ref(const char* src)
|
|
||||||
{
|
|
||||||
if (Owned && !is_using_local_buf())
|
|
||||||
STR_MEMFREE(Data);
|
|
||||||
Data = src ? (char*)src : EmptyBuffer;
|
|
||||||
Capacity = 0;
|
|
||||||
Owned = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Str::Str()
|
|
||||||
{
|
|
||||||
Data = EmptyBuffer; // Shared READ-ONLY initial buffer for 0 capacity
|
|
||||||
Capacity = 0;
|
|
||||||
LocalBufSize = 0;
|
|
||||||
Owned = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Str::Str(const Str& rhs) : Str()
|
|
||||||
{
|
|
||||||
set(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
Str::Str(const char* rhs) : Str()
|
|
||||||
{
|
|
||||||
set(rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
Str::Str(int amount, char character) : Str() {
|
|
||||||
set(amount, character);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Literal/reference string
|
|
||||||
class StrRef : public Str
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
StrRef(const char* s) : Str() { set_ref(s); }
|
|
||||||
};
|
|
||||||
|
|
||||||
#define STR_DEFINETYPE(TYPENAME, LOCALBUFSIZE) \
|
|
||||||
class TYPENAME : public Str \
|
|
||||||
{ \
|
|
||||||
char local_buf[LOCALBUFSIZE]; \
|
|
||||||
public: \
|
|
||||||
TYPENAME() : Str(LOCALBUFSIZE) {} \
|
|
||||||
TYPENAME(const Str& rhs) : Str(LOCALBUFSIZE) { set(rhs); } \
|
|
||||||
TYPENAME(const char* rhs) : Str(LOCALBUFSIZE) { set(rhs); } \
|
|
||||||
TYPENAME(const TYPENAME& rhs) : Str(LOCALBUFSIZE) { set(rhs); } \
|
|
||||||
TYPENAME& operator=(const char* rhs) { set(rhs); return *this; } \
|
|
||||||
TYPENAME& operator=(const Str& rhs) { set(rhs); return *this; } \
|
|
||||||
TYPENAME& operator=(const TYPENAME& rhs) { set(rhs); return *this; } \
|
|
||||||
};
|
|
||||||
|
|
||||||
// Disable PVS-Studio warning V730: Not all members of a class are initialized inside the constructor (local_buf is not initialized and that is fine)
|
|
||||||
// -V:STR_DEFINETYPE:730
|
|
||||||
|
|
||||||
// Helper to define StrXXXf constructors
|
|
||||||
#define STR_DEFINETYPE_F(TYPENAME, TYPENAME_F) \
|
|
||||||
class TYPENAME_F : public TYPENAME \
|
|
||||||
{ \
|
|
||||||
public: \
|
|
||||||
TYPENAME_F(const char* fmt, ...) : TYPENAME() { va_list args; va_start(args, fmt); setfv(fmt, args); va_end(args); } \
|
|
||||||
};
|
|
||||||
|
|
||||||
#ifdef __clang__
|
|
||||||
#pragma clang diagnostic push
|
|
||||||
#pragma clang diagnostic ignored "-Wunused-private-field" // warning : private field 'local_buf' is not used
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Declaring types for common sizes here
|
|
||||||
STR_DEFINETYPE(Str16, 16)
|
|
||||||
STR_DEFINETYPE(Str30, 30)
|
|
||||||
STR_DEFINETYPE(Str64, 64)
|
|
||||||
STR_DEFINETYPE(Str128, 128)
|
|
||||||
STR_DEFINETYPE(Str256, 256)
|
|
||||||
STR_DEFINETYPE(Str512, 512)
|
|
||||||
|
|
||||||
// Declaring helper constructors to pass in format strings in one statement
|
|
||||||
STR_DEFINETYPE_F(Str16, Str16f)
|
|
||||||
STR_DEFINETYPE_F(Str30, Str30f)
|
|
||||||
STR_DEFINETYPE_F(Str64, Str64f)
|
|
||||||
STR_DEFINETYPE_F(Str128, Str128f)
|
|
||||||
STR_DEFINETYPE_F(Str256, Str256f)
|
|
||||||
STR_DEFINETYPE_F(Str512, Str512f)
|
|
||||||
|
|
||||||
#if STR_DEFINE_STR32
|
|
||||||
STR_DEFINETYPE(Str32, 32)
|
|
||||||
STR_DEFINETYPE_F(Str32, Str32f)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __clang__
|
|
||||||
#pragma clang diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif // #ifndef STR_INCLUDED
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
// IMPLEMENTATION
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
|
|
||||||
#ifdef STR_IMPLEMENTATION
|
|
||||||
|
|
||||||
#include <stdio.h> // for vsnprintf
|
|
||||||
|
|
||||||
// On some platform vsnprintf() takes va_list by reference and modifies it.
|
|
||||||
// va_copy is the 'correct' way to copy a va_list but Visual Studio prior to 2013 doesn't have it.
|
|
||||||
#ifndef va_copy
|
|
||||||
#define va_copy(dest, src) (dest = src)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Static empty buffer we can point to for empty strings
|
|
||||||
// Pointing to a literal increases the like-hood of getting a crash if someone attempts to write in the empty string buffer.
|
|
||||||
char* Str::EmptyBuffer = (char*)"\0NULL";
|
|
||||||
|
|
||||||
// Clear
|
|
||||||
void Str::clear()
|
|
||||||
{
|
|
||||||
if (Owned && !is_using_local_buf())
|
|
||||||
STR_MEMFREE(Data);
|
|
||||||
if (LocalBufSize)
|
|
||||||
{
|
|
||||||
Data = local_buf();
|
|
||||||
Data[0] = '\0';
|
|
||||||
Capacity = LocalBufSize - 1;
|
|
||||||
Owned = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Data = EmptyBuffer;
|
|
||||||
Capacity = 0;
|
|
||||||
Owned = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reserve memory, preserving the current of the buffer
|
|
||||||
// Capacity doesn't include the zero terminator, so reserve(5) is enough to store "hello".
|
|
||||||
void Str::reserve(int new_capacity)
|
|
||||||
{
|
|
||||||
if (new_capacity <= Capacity)
|
|
||||||
return;
|
|
||||||
|
|
||||||
char* new_data;
|
|
||||||
if (new_capacity <= LocalBufSize - 1)
|
|
||||||
{
|
|
||||||
// Disowned -> LocalBuf
|
|
||||||
new_data = local_buf();
|
|
||||||
new_capacity = LocalBufSize - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Disowned or LocalBuf -> Heap
|
|
||||||
new_data = (char*)STR_MEMALLOC((size_t)(new_capacity + 1) * sizeof(char));
|
|
||||||
}
|
|
||||||
|
|
||||||
// string in Data might be longer than new_capacity if it wasn't owned, don't copy too much
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
strncpy_s(new_data, (size_t)new_capacity + 1, Data, (size_t)new_capacity);
|
|
||||||
#else
|
|
||||||
strncpy(new_data, Data, (size_t)new_capacity);
|
|
||||||
#endif
|
|
||||||
new_data[new_capacity] = 0;
|
|
||||||
|
|
||||||
if (Owned && !is_using_local_buf())
|
|
||||||
STR_MEMFREE(Data);
|
|
||||||
|
|
||||||
Data = new_data;
|
|
||||||
Capacity = new_capacity;
|
|
||||||
Owned = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reserve memory, discarding the current of the buffer (if we expect to be fully rewritten)
|
|
||||||
void Str::reserve_discard(int new_capacity)
|
|
||||||
{
|
|
||||||
if (new_capacity <= Capacity)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (Owned && !is_using_local_buf())
|
|
||||||
STR_MEMFREE(Data);
|
|
||||||
|
|
||||||
if (new_capacity <= LocalBufSize - 1)
|
|
||||||
{
|
|
||||||
// Disowned -> LocalBuf
|
|
||||||
Data = local_buf();
|
|
||||||
Capacity = LocalBufSize - 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Disowned or LocalBuf -> Heap
|
|
||||||
Data = (char*)STR_MEMALLOC((size_t)(new_capacity + 1) * sizeof(char));
|
|
||||||
Capacity = new_capacity;
|
|
||||||
}
|
|
||||||
Owned = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Str::shrink_to_fit()
|
|
||||||
{
|
|
||||||
if (!Owned || is_using_local_buf())
|
|
||||||
return;
|
|
||||||
int new_capacity = length();
|
|
||||||
if (Capacity <= new_capacity)
|
|
||||||
return;
|
|
||||||
|
|
||||||
char* new_data = (char*)STR_MEMALLOC((size_t)(new_capacity + 1) * sizeof(char));
|
|
||||||
memcpy(new_data, Data, (size_t)(new_capacity + 1));
|
|
||||||
STR_MEMFREE(Data);
|
|
||||||
Data = new_data;
|
|
||||||
Capacity = new_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: merge setfv() and appendfv()?
|
|
||||||
int Str::setfv(const char* fmt, va_list args)
|
|
||||||
{
|
|
||||||
// Needed for portability on platforms where va_list are passed by reference and modified by functions
|
|
||||||
va_list args2;
|
|
||||||
va_copy(args2, args);
|
|
||||||
|
|
||||||
// MSVC returns -1 on overflow when writing, which forces us to do two passes
|
|
||||||
// FIXME-OPT: Find a way around that.
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
int len = vsnprintf(NULL, 0, fmt, args);
|
|
||||||
STR_ASSERT(len >= 0);
|
|
||||||
|
|
||||||
if (Capacity < len)
|
|
||||||
reserve_discard(len);
|
|
||||||
len = vsnprintf(Data, (size_t)len + 1, fmt, args2);
|
|
||||||
#else
|
|
||||||
// First try
|
|
||||||
int len = vsnprintf(Owned ? Data : NULL, Owned ? (size_t)(Capacity + 1): 0, fmt, args);
|
|
||||||
STR_ASSERT(len >= 0);
|
|
||||||
|
|
||||||
if (Capacity < len)
|
|
||||||
{
|
|
||||||
reserve_discard(len);
|
|
||||||
len = vsnprintf(Data, (size_t)len + 1, fmt, args2);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
STR_ASSERT(Owned);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Str::setf(const char* fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
int len = setfv(fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Str::setfv_nogrow(const char* fmt, va_list args)
|
|
||||||
{
|
|
||||||
STR_ASSERT(Owned);
|
|
||||||
|
|
||||||
if (Capacity == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int w = vsnprintf(Data, (size_t)(Capacity + 1), fmt, args);
|
|
||||||
Data[Capacity] = 0;
|
|
||||||
Owned = 1;
|
|
||||||
return (w == -1) ? Capacity : w;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Str::setf_nogrow(const char* fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
int len = setfv_nogrow(fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Str::append_from(int idx, char c)
|
|
||||||
{
|
|
||||||
int add_len = 1;
|
|
||||||
if (Capacity < idx + add_len)
|
|
||||||
reserve(idx + add_len);
|
|
||||||
Data[idx] = c;
|
|
||||||
Data[idx + add_len] = 0;
|
|
||||||
STR_ASSERT(Owned);
|
|
||||||
return add_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Str::append_from(int idx, const char* s, const char* s_end)
|
|
||||||
{
|
|
||||||
if (!s_end)
|
|
||||||
s_end = s + strlen(s);
|
|
||||||
int add_len = (int)(s_end - s);
|
|
||||||
if (Capacity < idx + add_len)
|
|
||||||
reserve(idx + add_len);
|
|
||||||
memcpy(Data + idx, (const void*)s, (size_t)add_len);
|
|
||||||
Data[idx + add_len] = 0; // Our source data isn't necessarily zero terminated
|
|
||||||
STR_ASSERT(Owned);
|
|
||||||
return add_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: merge setfv() and appendfv()?
|
|
||||||
int Str::appendfv_from(int idx, const char* fmt, va_list args)
|
|
||||||
{
|
|
||||||
// Needed for portability on platforms where va_list are passed by reference and modified by functions
|
|
||||||
va_list args2;
|
|
||||||
va_copy(args2, args);
|
|
||||||
|
|
||||||
// MSVC returns -1 on overflow when writing, which forces us to do two passes
|
|
||||||
// FIXME-OPT: Find a way around that.
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
int add_len = vsnprintf(NULL, 0, fmt, args);
|
|
||||||
STR_ASSERT(add_len >= 0);
|
|
||||||
|
|
||||||
if (Capacity < idx + add_len)
|
|
||||||
reserve(idx + add_len);
|
|
||||||
add_len = vsnprintf(Data + idx, add_len + 1, fmt, args2);
|
|
||||||
#else
|
|
||||||
// First try
|
|
||||||
int add_len = vsnprintf(Owned ? Data + idx : NULL, Owned ? (size_t)(Capacity + 1 - idx) : 0, fmt, args);
|
|
||||||
STR_ASSERT(add_len >= 0);
|
|
||||||
|
|
||||||
if (Capacity < idx + add_len)
|
|
||||||
{
|
|
||||||
reserve(idx + add_len);
|
|
||||||
add_len = vsnprintf(Data + idx, (size_t)add_len + 1, fmt, args2);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
STR_ASSERT(Owned);
|
|
||||||
return add_len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Str::appendf_from(int idx, const char* fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
int len = appendfv_from(idx, fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Str::append(char c)
|
|
||||||
{
|
|
||||||
int cur_len = length();
|
|
||||||
return append_from(cur_len, c);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Str::append(const char* s, const char* s_end)
|
|
||||||
{
|
|
||||||
int cur_len = length();
|
|
||||||
return append_from(cur_len, s, s_end);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Str::appendfv(const char* fmt, va_list args)
|
|
||||||
{
|
|
||||||
int cur_len = length();
|
|
||||||
return appendfv_from(cur_len, fmt, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
int Str::appendf(const char* fmt, ...)
|
|
||||||
{
|
|
||||||
va_list args;
|
|
||||||
va_start(args, fmt);
|
|
||||||
int len = appendfv(fmt, args);
|
|
||||||
va_end(args);
|
|
||||||
return len;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // #define STR_IMPLEMENTATION
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
# Str
|
|
||||||
|
|
||||||
Simple C++ string type with an optional local buffer, by Omar Cornut
|
|
||||||
https://github.com/ocornut/str
|
|
||||||
|
|
||||||
**LICENSE**
|
|
||||||
|
|
||||||
This software is in the public domain. Where that dedication is not
|
|
||||||
recognized, you are granted a perpetual, irrevocable license to copy,
|
|
||||||
distribute, and modify this file as you see fit.
|
|
||||||
|
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
#define STR_IMPLEMENTATION
|
|
||||||
#include "Str.h"
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <tt_lock.h>
|
|
||||||
|
|
||||||
class ScopedLock;
|
|
||||||
|
|
||||||
/** Represents a lock/mutex */
|
|
||||||
class Lock {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
virtual ~Lock() = default;
|
|
||||||
|
|
||||||
virtual bool lock(TickType timeout) const = 0;
|
|
||||||
|
|
||||||
bool lock() const { return lock(TT_MAX_TICKS); }
|
|
||||||
|
|
||||||
virtual bool unlock() const = 0;
|
|
||||||
|
|
||||||
ScopedLock asScopedLock() const;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a lockable instance that is scoped to a specific lifecycle.
|
|
||||||
* Once the ScopedLock is destroyed, unlock() is called automatically.
|
|
||||||
*
|
|
||||||
* In other words:
|
|
||||||
* You have to lock() this object manually, but unlock() happens automatically on destruction.
|
|
||||||
*/
|
|
||||||
class ScopedLock final : public Lock {
|
|
||||||
|
|
||||||
const Lock& lockable;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
using Lock::lock;
|
|
||||||
|
|
||||||
explicit ScopedLock(const Lock& lockable) : lockable(lockable) {}
|
|
||||||
|
|
||||||
~ScopedLock() override {
|
|
||||||
lockable.unlock(); // We don't care whether it succeeded or not
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lock(TickType timeout) const override {
|
|
||||||
return lockable.lock(timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool unlock() const override {
|
|
||||||
return lockable.unlock();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,21 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <TactilityCpp/Lock.h>
|
#include <Tactility/Lock.h>
|
||||||
#include <tt_lvgl.h>
|
#include <tt_lvgl.h>
|
||||||
|
|
||||||
class LvglLock final : public Lock {
|
class LvglLock final : public tt::Lock {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
bool lock(TickType timeout = TT_MAX_TICKS) const override {
|
bool lock(TickType_t timeout = tt::kernel::MAX_TICKS) const override {
|
||||||
tt_lvgl_lock(timeout);
|
return tt_lvgl_lock(timeout);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool unlock() const override {
|
void unlock() const override {
|
||||||
tt_lvgl_unlock();
|
tt_lvgl_unlock();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <tt_lock.h>
|
|
||||||
#include <TactilityCpp/Lock.h>
|
|
||||||
|
|
||||||
class Mutex final : public Lock {
|
|
||||||
|
|
||||||
LockHandle handle;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
explicit Mutex(TtMutexType type) : handle(tt_lock_alloc_mutex(type)) {};
|
|
||||||
|
|
||||||
~Mutex() override {
|
|
||||||
tt_lock_free(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lock(TickType timeout = TT_MAX_TICKS) const override {
|
|
||||||
return tt_lock_acquire(handle, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool unlock() const override {
|
|
||||||
return tt_lock_release(handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <tt_thread.h>
|
|
||||||
|
|
||||||
class Thread {
|
|
||||||
ThreadHandle handle;
|
|
||||||
public:
|
|
||||||
|
|
||||||
Thread() : handle(tt_thread_alloc()) {}
|
|
||||||
|
|
||||||
Thread(
|
|
||||||
const char* name,
|
|
||||||
uint32_t stackSize,
|
|
||||||
ThreadCallback callback,
|
|
||||||
void* _Nullable callbackContext
|
|
||||||
) : handle(tt_thread_alloc_ext(name, stackSize, callback, callbackContext)) {}
|
|
||||||
|
|
||||||
~Thread() {
|
|
||||||
tt_thread_free(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
void start() const {
|
|
||||||
tt_thread_start(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool join(TickType timeout = TT_MAX_TICKS) const {
|
|
||||||
return tt_thread_join(handle, timeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setName(const char* name) const {
|
|
||||||
tt_thread_set_name(handle, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStackSize(size_t stackSize) const {
|
|
||||||
tt_thread_set_stack_size(handle, stackSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setAffinity(int affinity) const {
|
|
||||||
tt_thread_set_affinity(handle, affinity);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setCallback(ThreadCallback callback, void* _Nullable callbackContext) const {
|
|
||||||
tt_thread_set_callback(handle, callback, callbackContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setPriority(ThreadPriority priority) const {
|
|
||||||
tt_thread_set_priority(handle, priority);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStateCallback(ThreadStateCallback callback, void* _Nullable callbackContext) const {
|
|
||||||
tt_thread_set_state_callback(handle, callback, callbackContext);
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadState getState() const {
|
|
||||||
return tt_thread_get_state(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
ThreadId getId() const {
|
|
||||||
return tt_thread_get_id(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
int32_t getReturnCode() const {
|
|
||||||
return tt_thread_get_return_code(handle);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <tt_hal_uart.h>
|
#include <tt_hal_uart.h>
|
||||||
#include <Str.h>
|
#include <memory>
|
||||||
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <freertos/FreeRTOS.h>
|
||||||
|
|
||||||
class Uart {
|
class Uart {
|
||||||
UartHandle handle;
|
UartHandle handle;
|
||||||
@@ -20,13 +22,13 @@ public:
|
|||||||
return std::make_unique<Uart>(handle);
|
return std::make_unique<Uart>(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<Str> getNames() {
|
static std::vector<std::string> getNames() {
|
||||||
std::vector<Str> names;
|
std::vector<std::string> names;
|
||||||
size_t count = tt_hal_uart_get_count();
|
size_t count = tt_hal_uart_get_count();
|
||||||
for (size_t i = 0; i < count; i++) {
|
for (size_t i = 0; i < count; i++) {
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
if (tt_hal_uart_get_name(i, buffer, sizeof(buffer))) {
|
if (tt_hal_uart_get_name(i, buffer, sizeof(buffer))) {
|
||||||
names.push_back(Str(buffer));
|
names.push_back(std::string(buffer));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return names;
|
return names;
|
||||||
@@ -44,15 +46,15 @@ public:
|
|||||||
return tt_hal_uart_stop(handle);
|
return tt_hal_uart_stop(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t readBytes(char* buffer, size_t bufferSize, TickType timeout) const {
|
size_t readBytes(char* buffer, size_t bufferSize, TickType_t timeout) const {
|
||||||
return tt_hal_uart_read_bytes(handle, buffer, bufferSize, timeout);
|
return tt_hal_uart_read_bytes(handle, buffer, bufferSize, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool readByte(char* output, TickType timeout) const {
|
bool readByte(char* output, TickType_t timeout) const {
|
||||||
return tt_hal_uart_read_bytes(handle, output, 1, timeout);
|
return tt_hal_uart_read_bytes(handle, output, 1, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t writeBytes(const char* buffer, size_t bufferSize, TickType timeout) const {
|
size_t writeBytes(const char* buffer, size_t bufferSize, TickType_t timeout) const {
|
||||||
return tt_hal_uart_write_bytes(handle, buffer, bufferSize, timeout);
|
return tt_hal_uart_write_bytes(handle, buffer, bufferSize, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
#include <TactilityCpp/Lock.h>
|
|
||||||
|
|
||||||
ScopedLock Lock::asScopedLock() const {
|
|
||||||
return ScopedLock(*this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user