Compare commits

..

No commits in common. "fa544f9b3c49b09cd9ccb99e20cda9d28b90fe1b" and "7283920def18d5826cb4d7fc64ee5d2b276a7021" have entirely different histories.

32 changed files with 729 additions and 284 deletions

View File

@ -6,10 +6,10 @@ runs:
- name: 'Download artifacts'
uses: actions/download-artifact@v4
with:
path: artifacts
path: firmwares
- name: 'Upload Artifact'
uses: actions/upload-artifact@v4
with:
name: 'all-artifacts'
path: artifacts/
name: 'all-firmwares'
path: firmwares/
retention-days: 3

View File

@ -8,17 +8,17 @@ inputs:
runs:
using: 'composite'
steps:
- name: 'Download all-artifacts'
- name: 'Download all-firmwares'
uses: actions/download-artifact@v4
with:
name: 'all-artifacts'
path: artifacts
name: 'all-firmwares'
path: firmwares
- name: 'Install boto3'
shell: bash
run: pip install boto3
- name: 'Generate files'
shell: bash
run: version=`cat version.txt` && python Buildscripts/CDN/generate-firmware-files.py artifacts artifacts-cdn $version
run: version=`cat version.txt` && python Buildscripts/CDN/generate-files.py firmwares firmwares-cdn $version
- name: 'Upload files'
shell: bash
run: python Buildscripts/CDN/upload-firmware-files.py artifacts-cdn ${{ inputs.cdn_version }} ${{ env.CDN_ID }} ${{ env.CDN_TOKEN_NAME }} ${{ env.CDN_TOKEN_VALUE }}
run: python Buildscripts/CDN/upload-files.py firmwares-cdn ${{ inputs.cdn_version }} ${{ env.CDN_ID }} ${{ env.CDN_TOKEN_NAME }} ${{ env.CDN_TOKEN_VALUE }}

View File

@ -1,19 +0,0 @@
name: Publish SDK
runs:
using: 'composite'
steps:
- name: 'Download all-artifacts'
uses: actions/download-artifact@v4
with:
name: 'all-artifacts'
path: artifacts
- name: 'Install boto3'
shell: bash
run: pip install boto3
- name: 'Generate files'
shell: bash
run: version=`cat version.txt` && python Buildscripts/CDN/generate-sdk-files.py artifacts artifacts-cdn $version
- name: 'Upload files'
shell: bash
run: version=`cat version.txt` && python Buildscripts/CDN/upload-sdk-files.py artifacts-cdn $version ${{ env.CDN_ID }} ${{ env.CDN_TOKEN_NAME }} ${{ env.CDN_TOKEN_VALUE }}

View File

@ -78,7 +78,7 @@ jobs:
with:
board_id: ${{ matrix.board.id }}
arch: ${{ matrix.board.arch }}
BundleArtifacts:
BundleFirmware:
runs-on: ubuntu-latest
needs: [ BuildFirmware ]
if: |
@ -86,11 +86,11 @@ jobs:
(github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
steps:
- uses: actions/checkout@v4
- name: "Bundle Artifacts"
uses: ./.github/actions/bundle-artifacts
- name: "Bundle Firmware"
uses: ./.github/actions/bundle-firmware
PublishFirmwareSnapshot:
runs-on: ubuntu-latest
needs: [ BundleArtifacts ]
needs: [ BundleFirmware ]
if: (github.event_name == 'push' && github.ref == 'refs/heads/main')
steps:
- uses: actions/checkout@v4
@ -104,7 +104,7 @@ jobs:
cdn_version: snapshot
PublishFirmwareStable:
runs-on: ubuntu-latest
needs: [ BundleArtifacts ]
needs: [ BundleFirmware ]
if: (github.event_name == 'push' && startsWith(github.ref, 'refs/tags/v'))
steps:
- uses: actions/checkout@v4
@ -115,16 +115,4 @@ jobs:
CDN_TOKEN_VALUE: ${{ secrets.CDN_TOKEN_VALUE }}
uses: ./.github/actions/publish-firmware
with:
cdn_version: stable
PublishSdk:
runs-on: ubuntu-latest
needs: [ BundleArtifacts ]
if: (github.event_name == 'push' && (github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/tags/v')))
steps:
- uses: actions/checkout@v4
- name: "Publish SDKs"
env:
CDN_ID: ${{ secrets.CDN_ID }}
CDN_TOKEN_NAME: ${{ secrets.CDN_TOKEN_NAME }}
CDN_TOKEN_VALUE: ${{ secrets.CDN_TOKEN_VALUE }}
uses: ./.github/actions/publish-sdk
cdn_version: stable

View File

@ -45,9 +45,14 @@ class DeviceIndex:
gitCommit: str
devices: list
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_reset = "\033[m"
if sys.platform == "win32":
shell_color_red = ""
shell_color_orange = ""
shell_color_reset = ""
else:
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_reset = "\033[m"
def print_warning(message):
print(f"{shell_color_orange}WARNING: {message}{shell_color_reset}")
@ -56,7 +61,7 @@ def print_error(message):
print(f"{shell_color_red}ERROR: {message}{shell_color_reset}")
def print_help():
print("Usage: python generate-firmware-files.py [inPath] [outPath] [version]")
print("Usage: python generate-files.py [inPath] [outPath] [version]")
print(" inPath path with the extracted release files")
print(" outPath path where the CDN files will become available")
print(" version technical version name (e.g. 1.2.0)")
@ -223,7 +228,7 @@ if __name__ == "__main__":
# Argument validation
if len(sys.argv) < 4:
print_help()
sys.exit(1)
sys.exit()
if "--verbose" in sys.argv:
VERBOSE = True
sys.argv.remove("--verbose")

View File

@ -1,86 +0,0 @@
import subprocess
from datetime import datetime, UTC
import os
import sys
from dataclasses import dataclass, asdict
import json
import shutil
VERBOSE = False
@dataclass
class SdkIndex:
version: str
created: str
gitCommit: str
platforms: dict
shell_color_red = "\033[91m"
shell_color_orange = "\033[93m"
shell_color_reset = "\033[m"
def print_warning(message):
print(f"{shell_color_orange}WARNING: {message}{shell_color_reset}")
def print_error(message):
print(f"{shell_color_red}ERROR: {message}{shell_color_reset}")
def exit_with_error(message):
print_error(message)
sys.exit(1)
def print_help():
print("Usage: python generate-sdk-files.py [inPath] [outPath] [version]")
print(" inPath path with the extracted release files")
print(" outPath path where the CDN files will become available")
print(" version technical version name (e.g. 1.2.0)")
print("Options:")
print(" --verbose Show extra console output")
def get_git_commit_hash():
return subprocess.check_output(['git', 'rev-parse', 'HEAD']).decode('ascii').strip()
def main(in_path: str, out_path: str, version: str):
if not os.path.exists(in_path):
exit_with_error(f"Input path not found: {in_path}")
if os.path.exists(out_path):
shutil.rmtree(out_path)
os.mkdir(out_path)
artifact_directories = os.listdir(in_path)
sdk_index = SdkIndex(
version=version,
created=datetime.now(UTC).strftime('%Y-%m-%dT%H:%M:%S'),
gitCommit=get_git_commit_hash(),
platforms={}
)
for artifact_directory in artifact_directories:
if VERBOSE:
print(f"Processing {in_path}/{artifact_directory}")
if not artifact_directory.startswith("TactilitySDK-"):
continue
sdk_platform = artifact_directory.removeprefix("TactilitySDK-")
if not sdk_platform:
exit_with_error(f"Cannot derive platform from directory name: {artifact_directory}")
sdk_index.platforms[sdk_platform] = f"{artifact_directory}.zip"
if VERBOSE:
print(f"Archiving {in_path}/{artifact_directory} to {out_path}/{artifact_directory}.zip")
shutil.make_archive(os.path.join(out_path, artifact_directory), 'zip', os.path.join(in_path, artifact_directory))
index_file_path = os.path.join(out_path, "index.json")
if VERBOSE:
print(f"Generating {index_file_path}")
with open(index_file_path, "w") as index_file:
json.dump(asdict(sdk_index), index_file, indent=2)
if __name__ == "__main__":
print("Tactility CDN SDK File Generator")
if "--help" in sys.argv:
print_help()
sys.exit()
# Argument validation
if len(sys.argv) < 4:
print_help()
sys.exit(1)
if "--verbose" in sys.argv:
VERBOSE = True
sys.argv.remove("--verbose")
main(in_path=sys.argv[1], out_path=sys.argv[2], version=sys.argv[3])

View File

@ -2,9 +2,14 @@ import os
import sys
import boto3
SHELL_COLOR_RED = "\033[91m"
SHELL_COLOR_ORANGE = "\033[93m"
SHELL_COLOR_RESET = "\033[m"
if sys.platform == "win32":
SHELL_COLOR_RED = ""
SHELL_COLOR_ORANGE = ""
SHELL_COLOR_RESET = ""
else:
SHELL_COLOR_RED = "\033[91m"
SHELL_COLOR_ORANGE = "\033[93m"
SHELL_COLOR_RESET = "\033[m"
def print_warning(message):
print(f"{SHELL_COLOR_ORANGE}WARNING: {message}{SHELL_COLOR_RESET}")
@ -13,7 +18,7 @@ def print_error(message):
print(f"{SHELL_COLOR_RED}ERROR: {message}{SHELL_COLOR_RESET}")
def print_help():
print("Usage: python upload-firmware-files.py [path] [version] [cloudflareAccountId] [cloudflareTokenName] [cloudflareTokenValue]")
print("Usage: python upload-files.py [path] [version] [cloudflareAccountId] [cloudflareTokenName] [cloudflareTokenValue]")
print("")
print("Options:")
print(" --index-only Upload only index.json")
@ -47,14 +52,14 @@ def main(path: str, version: str, cloudflare_account_id, cloudflare_token_name:
counter += 1
if __name__ == "__main__":
print("Tactility CDN Firmware Uploader")
print("Tactility CDN Uploader")
if "--help" in sys.argv:
print_help()
sys.exit()
# Argument validation
if len(sys.argv) < 6:
print_help()
sys.exit(1)
sys.exit()
main(
path=sys.argv[1],
version=sys.argv[2],

View File

@ -1,65 +0,0 @@
import os
import sys
import boto3
SHELL_COLOR_RED = "\033[91m"
SHELL_COLOR_ORANGE = "\033[93m"
SHELL_COLOR_RESET = "\033[m"
def print_warning(message):
print(f"{SHELL_COLOR_ORANGE}WARNING: {message}{SHELL_COLOR_RESET}")
def print_error(message):
print(f"{SHELL_COLOR_RED}ERROR: {message}{SHELL_COLOR_RESET}")
def print_help():
print("Usage: python upload-sdk-files.py [path] [version] [cloudflareAccountId] [cloudflareTokenName] [cloudflareTokenValue]")
print("")
print("Options:")
print(" --index-only Upload only index.json")
def exit_with_error(message):
print_error(message)
sys.exit(1)
def main(path: str, version: str, cloudflare_account_id, cloudflare_token_name: str, cloudflare_token_value: str, index_only: bool):
if not os.path.exists(path):
exit_with_error(f"Path not found: {path}")
s3 = boto3.client(
service_name="s3",
endpoint_url=f"https://{cloudflare_account_id}.r2.cloudflarestorage.com",
aws_access_key_id=cloudflare_token_name,
aws_secret_access_key=cloudflare_token_value,
region_name="auto"
)
files_to_upload = os.listdir(path)
counter = 1
total = len(files_to_upload)
for file_name in files_to_upload:
if not index_only or file_name == 'index.json':
object_path = f"sdk/{version}/{file_name}"
print(f"[{counter}/{total}] Uploading {file_name} to {object_path}")
file_path = os.path.join(path, file_name)
try:
s3.upload_file(file_path, "tactility", object_path)
except Exception as e:
exit_with_error(f"Failed to upload {file_name}: {str(e)}")
counter += 1
if __name__ == "__main__":
print("Tactility CDN SDK Uploader")
if "--help" in sys.argv:
print_help()
sys.exit()
# Argument validation
if len(sys.argv) < 6:
print_help()
sys.exit(1)
main(
path=sys.argv[1],
version=sys.argv[2],
cloudflare_account_id=sys.argv[3],
cloudflare_token_name=sys.argv[4],
cloudflare_token_value=sys.argv[5],
index_only="--index-only" in sys.argv
)

View File

@ -1,6 +1,5 @@
idf_component_register(
INCLUDE_DIRS "Libraries/TactilityC/Include" "Libraries/lvgl/Include" "Libraries/TactilityFreeRtos/Include"
REQUIRES esp_timer
INCLUDE_DIRS "Libraries/TactilityC/Include" "Libraries/lvgl/Include"
)
add_prebuilt_library(TactilityC Libraries/TactilityC/Binary/libTactilityC.a)

View File

@ -8,12 +8,20 @@ else ()
set(TACTILITY_TARGET " @ Simulator")
endif ()
string(ASCII 27 Esc)
set(ColorReset "${Esc}[m")
set(Cyan "${Esc}[36m")
set(Grey "${Esc}[37m")
set(LightPurple "${Esc}[1;35m")
set(White "${Esc}[1;37m")
if (NOT WIN32)
string(ASCII 27 Esc)
set(ColorReset "${Esc}[m")
set(Cyan "${Esc}[36m")
set(Grey "${Esc}[37m")
set(LightPurple "${Esc}[1;35m")
set(White "${Esc}[1;37m")
else ()
set(ColorReset "")
set(Cyan "")
set(Grey "")
set(LightPurple "")
set(White "")
endif ()
# Some terminals (e.g. GitHub Actions) reset colour for every in a multiline message(),
# so we add the colour to each line instead of assuming it would automatically be re-used.

View File

@ -24,13 +24,6 @@ find_target_dir=$build_dir/$tactility_library_path/Include/
cp TactilityC/Include/* $find_target_dir
cp Documentation/license-tactilitysdk.md $build_dir/$tactility_library_path/LICENSE.md
# TactilityFreeRtos
tactilityfreertos_library_path=$library_path/TactilityFreeRtos
mkdir -p $tactilityfreertos_library_path/Include
find_target_dir=$build_dir/$tactilityfreertos_library_path/Include/
cp -r TactilityFreeRtos/Include/* $find_target_dir
cp Documentation/license-tactilitysdk.md $build_dir/$tactilityfreertos_library_path/LICENSE.md
# lvgl
lvgl_library_path=$library_path/lvgl
mkdir -p $lvgl_library_path/Binary

View File

@ -1,14 +1,21 @@
cmake_minimum_required(VERSION 3.20)
add_definitions(-DTT_DEBUG)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_ASM_COMPILE_OBJECT "${CMAKE_CXX_COMPILER_TARGET}")
include("Buildscripts/logo.cmake")
string(ASCII 27 Esc)
set(ColorReset "${Esc}[m")
set(Cyan "${Esc}[36m")
if (NOT WIN32)
string(ASCII 27 Esc)
set(ColorReset "${Esc}[m")
set(Cyan "${Esc}[36m")
else ()
set(ColorReset "")
set(Cyan "")
endif ()
file(READ version.txt TACTILITY_VERSION)
add_compile_definitions(TT_VERSION="${TACTILITY_VERSION}")
@ -70,16 +77,19 @@ if (NOT DEFINED ENV{ESP_IDF_VERSION})
add_subdirectory(TactilityCore)
add_subdirectory(TactilityFreeRtos)
add_subdirectory(Devices/simulator)
endif ()
if (NOT DEFINED ENV{ESP_IDF_VERSION})
# FreeRTOS
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "")
set(FREERTOS_PORT GCC_POSIX CACHE STRING "")
add_subdirectory(Libraries/cJSON)
add_subdirectory(Libraries/FreeRTOS-Kernel)
add_subdirectory(Libraries/lv_screenshot)
add_subdirectory(Libraries/QRCode)
add_subdirectory(Libraries/minitar)
add_subdirectory(Libraries/minmea)
# FreeRTOS
set(FREERTOS_CONFIG_FILE_DIRECTORY ${PROJECT_SOURCE_DIR}/Devices/simulator/Source CACHE STRING "")
set(FREERTOS_PORT GCC_POSIX CACHE STRING "")
add_subdirectory(Libraries/FreeRTOS-Kernel)
target_compile_definitions(freertos_kernel PUBLIC "projCOVERAGE_TEST=0")
target_include_directories(freertos_kernel
PUBLIC Devices/Simulator/Source # for FreeRTOSConfig.h

View File

@ -1,8 +1,8 @@
#pragma once
#include <tt_kernel.h>
#include <tt_hal_device.h>
#include <stdbool.h>
#include <freertos/FreeRTOS.h>
#ifdef __cplusplus
extern "C" {
@ -48,7 +48,7 @@ void tt_hal_display_driver_free(DisplayDriverHandle handle);
* @param[in] timeout the maximum amount of ticks to wait for getting a lock
* @return true if the lock was acquired
*/
bool tt_hal_display_driver_lock(DisplayDriverHandle handle, TickType_t timeout);
bool tt_hal_display_driver_lock(DisplayDriverHandle handle, TickType timeout);
/**
* Unlock the display device. Must be called exactly once after locking.

View File

@ -3,7 +3,7 @@
#include <stdbool.h>
#include <stdint.h>
#include <stddef.h>
#include <freertos/FreeRTOS.h>
#include <tt_kernel.h>
#ifdef __cplusplus
extern "C" {
@ -91,7 +91,7 @@ bool tt_hal_uart_stop(UartHandle handle);
* to wait indefinitely.
* @return The number of bytes read (0 on timeout with no data). Never exceeds bufferSize.
*/
size_t tt_hal_uart_read_bytes(UartHandle handle, char* buffer, size_t bufferSize, TickType_t timeout);
size_t tt_hal_uart_read_bytes(UartHandle handle, char* buffer, size_t bufferSize, TickType timeout);
/**
* @brief Read a single byte.
@ -102,7 +102,7 @@ size_t tt_hal_uart_read_bytes(UartHandle handle, char* buffer, size_t bufferSize
* to wait indefinitely.
* @return true if a byte was read and stored in output; false on timeout or failure.
*/
bool tt_hal_uart_read_byte(UartHandle handle, char* output, TickType_t timeout);
bool tt_hal_uart_read_byte(UartHandle handle, char* output, TickType timeout);
/**
* @brief Write up to bufferSize bytes from buffer.
@ -117,7 +117,7 @@ bool tt_hal_uart_read_byte(UartHandle handle, char* output, TickType_t timeout);
* to wait indefinitely.
* @return The number of bytes written (may be less than bufferSize on timeout).
*/
size_t tt_hal_uart_write_bytes(UartHandle handle, const char* buffer, size_t bufferSize, TickType_t timeout);
size_t tt_hal_uart_write_bytes(UartHandle handle, const char* buffer, size_t bufferSize, TickType timeout);
/**
* @brief Get the number of bytes currently available to read without blocking.

View File

@ -0,0 +1,14 @@
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef unsigned long TickType;
#define TT_MAX_TICKS ((TickType)(~(TickType)0))
#ifdef __cplusplus
}
#endif

View File

@ -1,7 +1,7 @@
#pragma once
#include "tt_kernel.h"
#include <stdbool.h>
#include <freertos/FreeRTOS.h>
#ifdef __cplusplus
extern "C" {
@ -15,6 +15,13 @@ typedef enum {
MutexTypeRecursive
} TtMutexType;
/**
* Allocate a new mutex instance
* @param[in] type specify if the mutex is either a normal one, or whether it can recursively (re)lock
* @return the allocated lock handle
*/
LockHandle tt_lock_alloc_mutex(TtMutexType type);
/**
* Allocate a lock for a file or folder.
* Locking is required before reading files for filesystems that are on a shared bus (e.g. SPI SD card sharing the bus with the display)
@ -29,7 +36,7 @@ LockHandle tt_lock_alloc_for_path(const char* path);
* @param[in] timeout the maximum amount of ticks to wait when trying to lock
* @return true when the lock was acquired
*/
bool tt_lock_acquire(LockHandle handle, TickType_t timeout);
bool tt_lock_acquire(LockHandle handle, TickType timeout);
/**
* Attempt to unlock the lock.

View File

@ -1,7 +1,6 @@
#pragma once
#include <stdbool.h>
#include <freertos/FreeRTOS.h>
#ifdef __cplusplus
extern "C" {
@ -19,7 +18,7 @@ void tt_lvgl_start();
void tt_lvgl_stop();
/** Lock the LVGL context. Call this before doing LVGL-related operations from a non-LVLG thread */
bool tt_lvgl_lock(TickType_t timeout);
bool tt_lvgl_lock(TickType timeout);
/** Unlock the LVGL context */
void tt_lvgl_unlock();

View File

@ -0,0 +1,54 @@
#pragma once
#include <freertos/FreeRTOS.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
/** A handle that represents a message queue instance */
typedef void* MessageQueueHandle;
/**
* Allocate a new message queue in memory.
* @param[in] capacity how many messages this queue can contain before it starts blocking input
* @param[in] messageSize the size of a message
*/
MessageQueueHandle tt_message_queue_alloc(uint32_t capacity, uint32_t messageSize);
/** Free up the memory of a queue (dealloc) */
void tt_message_queue_free(MessageQueueHandle handle);
/**
* Put (post) a message in the queue
* @param[in] handle the queue handle
* @param[in] message the message of the correct size - its data will be copied
* @param[timeout] timeout the amount of ticks to wait until the message is queued
* @return true if the item was successfully queued
*/
bool tt_message_queue_put(MessageQueueHandle handle, const void* message, TickType_t timeout);
/**
* Get the oldest message from the queue.
* @param[in] handle the queue handle
* @param[out] message a pointer to a message of the correct size
* @param[in] timeout the amount of ticks to wait until a message was copied
* @return true if a message was successfully copied
*/
bool tt_message_queue_get(MessageQueueHandle handle, void* message, TickType_t timeout);
/** @return the current amount of items in the queue */
uint32_t tt_message_queue_get_count(MessageQueueHandle handle);
/**
* Remove all items from the queue (if any)
*/
void tt_message_queue_reset(MessageQueueHandle handle);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,50 @@
#pragma once
#include <freertos/FreeRTOS.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#include <stdbool.h>
/** A handle that represents a semaphore instance */
typedef void* SemaphoreHandle;
/**
* Allocate a new semaphore instance.
* @param[in] maxCount the maximum counter value
* @param[in] initialCount the initial counter value
* @return the handle that represents the new instance
*/
SemaphoreHandle tt_semaphore_alloc(uint32_t maxCount, TickType_t initialCount);
/** Free up the memory of a specified semaphore instance */
void tt_semaphore_free(SemaphoreHandle handle);
/**
* Attempt to acquire a semaphore (increase counter)
* @param[in] handle the instance handle
* @param[in] timeout the maximum amount of ticks to wait while trying to acquire
* @return true on successfully acquiring the semaphore (counter is increased)
*/
bool tt_semaphore_acquire(SemaphoreHandle handle, TickType_t timeout);
/**
* Release an acquired semaphore (decrease counter)
* @param[in] handle the instance handle
* @return true on successfully releasing the semaphore (counter is decreased)
*/
bool tt_semaphore_release(SemaphoreHandle handle);
/**
* Get the counter value of this semaphore instance
* @param[in] handle the instance handle
* @return the current counter value (acquisition count)
*/
uint32_t tt_semaphore_get_count(SemaphoreHandle handle);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,156 @@
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#else
#include "FreeRTOS.h"
#include "task.h"
#endif
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
/** The handle that represents the thread insance */
typedef void* ThreadHandle;
/** The state of a thread instance */
typedef enum {
ThreadStateStopped,
ThreadStateStarting,
ThreadStateRunning,
} ThreadState;
/** The identifier that represents the thread */
typedef TaskHandle_t TaskHandle;
/** ThreadCallback Your callback to run in new thread
* @warning never use osThreadExit in Thread
*/
typedef int32_t (*ThreadCallback)(void* context);
/** Thread state change callback called upon thread state change
* @param state new thread state
* @param context callback context
*/
typedef void (*ThreadStateCallback)(ThreadState state, void* context);
typedef enum {
ThreadPriorityNone = 0U, /**< Uninitialized, choose system default */
ThreadPriorityIdle = 1U,
ThreadPriorityLowest = 2U,
ThreadPriorityLow = 3U,
ThreadPriorityNormal = 4U,
ThreadPriorityHigh = 5U,
ThreadPriorityHigher = 6U,
ThreadPriorityHighest = 7U
} ThreadPriority;
/** @return a thread handle that represents a newly allocated thread instance */
ThreadHandle tt_thread_alloc();
/**
* Allocate a thread and provide some common parameters so it's all ready to be started.
* @param[in] name the name of the thread
* @param[in] stackSize the size of the stack in bytes
* @param[in] callback the callback to call from the thread
* @param[in] callbackContext the data to pass to the callback
*/
ThreadHandle tt_thread_alloc_ext(
const char* name,
uint32_t stackSize,
ThreadCallback callback,
void* _Nullable callbackContext
);
/**
* Free up the memory of the thread that is represented by this handle
* @param[in] handle the thread instance handle
*/
void tt_thread_free(ThreadHandle handle);
/**
* Set the name of a thread
* @param[in] handle the thread instance handle
* @param[in] name the name to set
*/
void tt_thread_set_name(ThreadHandle handle, const char* name);
/**
* Set the stack size of the thread (in bytes)
* @param[in] handle the thread instance handle
* @param[in] the size of the thread in bytes
*/
void tt_thread_set_stack_size(ThreadHandle handle, size_t size);
/** Set CPu core affinity for this thread
* @param[in] handle the thread instance handle
* @param[in] affinity -1 means not pinned, otherwise it's the core id (e.g. 0 or 1 on ESP32)
*/
void tt_thread_set_affinity(ThreadHandle handle, int affinity);
/**
* Set the callback for a thread. This method is executed when the thread is started.
* @param[in] handle the thread instance handle
* @param[in] callback the callback to set
* @param[in] callbackContext the data to pass to the callback
*/
void tt_thread_set_callback(ThreadHandle handle, ThreadCallback callback, void* _Nullable callbackContext);
/**
* Set the priority of a thread
* @param[in] handle the thread instance handle
* @param[in] priority the priority to set
*/
void tt_thread_set_priority(ThreadHandle handle, ThreadPriority priority);
/**
* Set the state callback for a thread
* @param[in] handle the thread instance handle
* @param[in] callback the callback to set
* @param[in] callbackContext the data to pass to the callback
*/
void tt_thread_set_state_callback(ThreadHandle handle, ThreadStateCallback callback, void* _Nullable callbackContext);
/**
* @param[in] handle the thread instance handle
* @return the current state of a thread
*/
ThreadState tt_thread_get_state(ThreadHandle handle);
/**
* Start a thread
* @param[in] handle the thread instance handle
*/
void tt_thread_start(ThreadHandle handle);
/**
* Wait (block) for the thread to finish.
* @param[in] handle the thread instance handle
* @warning make sure you manually interrupt any logic in your thread (e.g. by an EventGroup or boolean+Mutex)
*/
bool tt_thread_join(ThreadHandle handle, TickType_t timeout);
/**
* Get thread task handle
* @param[in] handle the thread instance handle
* @return the task handle of a thread
* */
TaskHandle tt_thread_get_task_handle(ThreadHandle handle);
/**
* Get the return code of a thread
* @warning crashes when state is not "stopped"
* @param[in] handle the thread instance handle
* @return the return code of a thread or
*/
int32_t tt_thread_get_return_code(ThreadHandle handle);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,97 @@
#pragma once
#include "tt_kernel.h"
#include "tt_thread.h"
#include <stdint.h>
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/** The handle that represents a timer instance */
typedef void* TimerHandle;
/** The behaviour of the timer */
typedef enum {
TimerTypeOnce = 0, // Timer triggers once after time has passed
TimerTypePeriodic = 1 // Timer triggers repeatedly after time has passed
} TimerType;
typedef void (*TimerCallback)(void* context);
typedef void (*TimerPendingCallback)(void* context, uint32_t arg);
/**
* Create a new timer instance
* @param[in] callback the callback to call when the timer expires
* @param[in] callbackContext the data to pass to the callback
*/
TimerHandle tt_timer_alloc(TimerType type, TickType ticks, TimerCallback callback, void* callbackContext);
/** Free up the memory of a timer instance */
void tt_timer_free(TimerHandle handle);
/**
* Start the timer
* @param[in] handle the timer instance handle
* @return true when the timer was successfully started
*/
bool tt_timer_start(TimerHandle handle);
/**
* Restart an already started timer
* @param[in] handle the timer instance handle
* @param[in] interval the timer new interval
* @return true when the timer was successfully restarted
*/
bool tt_timer_reset_with_interval(TimerHandle handle, TickType interval);
/**
* Restart an already started timer
* @param[in] handle the timer instance handle
* @return true when the timer was successfully restarted
*/
bool tt_timer_reset(TimerHandle handle);
/**
* Stop a started timer
* @param[in] handle the timer instance handle
* @return true when the timer was successfully stopped
*/
bool tt_timer_stop(TimerHandle handle);
/**
* Check if a timer is started
* @param[in] handle the timer instance handle
* @return true when the timer is started (pending)
*/
bool tt_timer_is_running(TimerHandle handle);
/**
* Get the expiry time of a timer
* @param[in] handle the timer instance handle
* @return the absolute timestamp at which the timer will expire
*/
uint32_t tt_timer_get_expiry_time(TimerHandle handle);
/**
* Set the pending callback for a timer
* @param[in] handle the timer instance handle
* @param[in] callback the callback to set
* @param[in] callbackContext the context to pass to the callback
* @param[in] timeout the timeout for setting the callback
* @return when the callback was successfully set
*/
bool tt_timer_set_pending_callback(TimerHandle handle, TimerPendingCallback callback, void* callbackContext, uint32_t callbackArg, TickType_t timeout);
/**
* Set the thread priority for the callback of the timer
* @param[in] handle the timer instance handle
* @param[in] priority the thread priority to set
*/
void tt_timer_set_thread_priority(TimerHandle handle, ThreadPriority priority);
#ifdef __cplusplus
}
#endif

View File

@ -3,20 +3,12 @@
#include <symbols/freertos.h>
#include <freertos/FreeRTOS.h>
#include <freertos/event_groups.h>
#include <freertos/queue.h>
#include <freertos/semphr.h>
#include <Tactility/freertoscompat/RTOS.h>
#include <freertos/task.h>
#include <freertos/timers.h>
#include <freertos/event_groups.h>
const esp_elfsym freertos_symbols[] = {
// Task
ESP_ELFSYM_EXPORT(uxTaskGetStackHighWaterMark),
ESP_ELFSYM_EXPORT(uxTaskGetNumberOfTasks),
ESP_ELFSYM_EXPORT(uxTaskGetTaskNumber),
ESP_ELFSYM_EXPORT(uxTaskPriorityGet),
ESP_ELFSYM_EXPORT(uxTaskPriorityGetFromISR),
ESP_ELFSYM_EXPORT(vTaskDelay),
ESP_ELFSYM_EXPORT(vTaskDelete),
ESP_ELFSYM_EXPORT(vTaskDeleteWithCaps),
@ -36,10 +28,13 @@ const esp_elfsym freertos_symbols[] = {
ESP_ELFSYM_EXPORT(xTaskDelayUntil),
ESP_ELFSYM_EXPORT(xTaskGenericNotify),
ESP_ELFSYM_EXPORT(xTaskGenericNotifyFromISR),
ESP_ELFSYM_EXPORT(xTaskGetTickCount),
ESP_ELFSYM_EXPORT(xTaskGetTickCountFromISR),
ESP_ELFSYM_EXPORT(pvTaskGetThreadLocalStoragePointer),
ESP_ELFSYM_EXPORT(pvTaskIncrementMutexHeldCount),
ESP_ELFSYM_EXPORT(uxTaskGetStackHighWaterMark),
ESP_ELFSYM_EXPORT(uxTaskGetNumberOfTasks),
ESP_ELFSYM_EXPORT(uxTaskGetTaskNumber),
ESP_ELFSYM_EXPORT(uxTaskPriorityGet),
ESP_ELFSYM_EXPORT(uxTaskPriorityGetFromISR),
// EventGroup
ESP_ELFSYM_EXPORT(xEventGroupCreate),
ESP_ELFSYM_EXPORT(xEventGroupCreateWithCaps),
@ -54,6 +49,11 @@ const esp_elfsym freertos_symbols[] = {
ESP_ELFSYM_EXPORT(xEventGroupSync),
ESP_ELFSYM_EXPORT(xEventGroupWaitBits),
// Queue
ESP_ELFSYM_EXPORT(xQueueGenericCreate),
ESP_ELFSYM_EXPORT(xQueueGenericCreateStatic),
ESP_ELFSYM_EXPORT(xQueueGenericReset),
ESP_ELFSYM_EXPORT(xQueueGenericSend),
ESP_ELFSYM_EXPORT(xQueueGenericSendFromISR),
ESP_ELFSYM_EXPORT(vQueueDelete),
ESP_ELFSYM_EXPORT(vQueueDeleteWithCaps),
ESP_ELFSYM_EXPORT(vQueueSetQueueNumber),
@ -62,23 +62,7 @@ const esp_elfsym freertos_symbols[] = {
ESP_ELFSYM_EXPORT(uxQueueMessagesWaiting),
ESP_ELFSYM_EXPORT(uxQueueMessagesWaitingFromISR),
ESP_ELFSYM_EXPORT(uxQueueSpacesAvailable),
ESP_ELFSYM_EXPORT(xQueueCreateCountingSemaphore),
ESP_ELFSYM_EXPORT(xQueueCreateCountingSemaphoreStatic),
ESP_ELFSYM_EXPORT(xQueueCreateMutex),
ESP_ELFSYM_EXPORT(xQueueCreateMutexStatic),
ESP_ELFSYM_EXPORT(xQueueCreateSet),
ESP_ELFSYM_EXPORT(xQueueGetMutexHolder),
ESP_ELFSYM_EXPORT(xQueueGetMutexHolderFromISR),
ESP_ELFSYM_EXPORT(xQueueGiveMutexRecursive),
ESP_ELFSYM_EXPORT(xQueueTakeMutexRecursive),
ESP_ELFSYM_EXPORT(xQueueGenericCreate),
ESP_ELFSYM_EXPORT(xQueueGenericCreateStatic),
ESP_ELFSYM_EXPORT(xQueueGenericReset),
ESP_ELFSYM_EXPORT(xQueueGenericSend),
ESP_ELFSYM_EXPORT(xQueueGenericSendFromISR),
ESP_ELFSYM_EXPORT(xQueueSemaphoreTake),
// Timer
ESP_ELFSYM_EXPORT(pvTimerGetTimerID),
ESP_ELFSYM_EXPORT(xTimerCreate),
ESP_ELFSYM_EXPORT(xTimerCreateStatic),
ESP_ELFSYM_EXPORT(xTimerGenericCommand),
@ -87,15 +71,7 @@ const esp_elfsym freertos_symbols[] = {
ESP_ELFSYM_EXPORT(xTimerPendFunctionCall),
ESP_ELFSYM_EXPORT(xTimerPendFunctionCallFromISR),
ESP_ELFSYM_EXPORT(xTimerGetPeriod),
ESP_ELFSYM_EXPORT(uxTimerGetReloadMode),
ESP_ELFSYM_EXPORT(uxTimerGetTimerNumber),
ESP_ELFSYM_EXPORT(vTimerSetReloadMode),
ESP_ELFSYM_EXPORT(vTimerSetTimerID),
ESP_ELFSYM_EXPORT(vTimerSetTimerNumber),
// portmacro.h
ESP_ELFSYM_EXPORT(vPortYield),
ESP_ELFSYM_EXPORT(vPortEnterCritical),
ESP_ELFSYM_EXPORT(vPortExitCritical),
ESP_ELFSYM_EXPORT(xPortInIsrContext),
ESP_ELFSYM_EXPORT(xPortCanYield),
ESP_ELFSYM_EXPORT(xPortGetCoreID),

View File

@ -11,7 +11,6 @@ const esp_elfsym stl_symbols[] = {
{ "_ZSt28__throw_bad_array_new_lengthv", (void*)&(std::__throw_bad_array_new_length) },
{ "_ZSt25__throw_bad_function_callv", (void*)&(std::__throw_bad_function_call) },
{ "_ZSt20__throw_length_errorPKc", (void*)&(std::__throw_length_error) },
{ "_ZSt19__throw_logic_errorPKc", (void*)&std::__throw_logic_error },
// { "", (void*)&(std::) },
// delimiter
ESP_ELFSYM_END

View File

@ -55,7 +55,7 @@ void tt_hal_display_driver_free(DisplayDriverHandle handle) {
delete wrapper;
}
bool tt_hal_display_driver_lock(DisplayDriverHandle handle, TickType_t timeout) {
bool tt_hal_display_driver_lock(DisplayDriverHandle handle, TickType timeout) {
auto wrapper = static_cast<DriverWrapper*>(handle);
return wrapper->driver->getLock()->lock(timeout);
}

View File

@ -53,15 +53,15 @@ bool tt_hal_uart_stop(UartHandle handle) {
return HANDLE_AS_UART(handle)->stop();
}
size_t tt_hal_uart_read_bytes(UartHandle handle, char* buffer, size_t bufferSize, TickType_t timeout) {
size_t tt_hal_uart_read_bytes(UartHandle handle, char* buffer, size_t bufferSize, TickType timeout) {
return HANDLE_AS_UART(handle)->readBytes(reinterpret_cast<std::byte*>(buffer), bufferSize, timeout);
}
bool tt_hal_uart_read_byte(UartHandle handle, char* output, TickType_t timeout) {
bool tt_hal_uart_read_byte(UartHandle handle, char* output, TickType timeout) {
return HANDLE_AS_UART(handle)->readByte(reinterpret_cast<std::byte*>(output), timeout);
}
size_t tt_hal_uart_write_bytes(UartHandle handle, const char* buffer, size_t bufferSize, TickType_t timeout) {
size_t tt_hal_uart_write_bytes(UartHandle handle, const char* buffer, size_t bufferSize, TickType timeout) {
return HANDLE_AS_UART(handle)->writeBytes(reinterpret_cast<const std::byte*>(buffer), bufferSize, timeout);
}

View File

@ -17,8 +17,12 @@
#include "tt_lvgl_keyboard.h"
#include "tt_lvgl_spinner.h"
#include "tt_lvgl_toolbar.h"
#include "tt_message_queue.h"
#include "tt_preferences.h"
#include "tt_semaphore.h"
#include "tt_thread.h"
#include "tt_time.h"
#include "tt_timer.h"
#include "tt_wifi.h"
#include "symbols/esp_event.h"
@ -45,6 +49,7 @@
#include <esp_random.h>
#include <esp_sntp.h>
#include <esp_netif.h>
#include <esp_wifi.h>
#include <dirent.h>
#include <sys/stat.h>
#include <time.h>
@ -194,6 +199,7 @@ const esp_elfsym main_symbols[] {
ESP_ELFSYM_EXPORT(tt_app_get_user_data_child_path),
ESP_ELFSYM_EXPORT(tt_app_get_assets_path),
ESP_ELFSYM_EXPORT(tt_app_get_assets_child_path),
ESP_ELFSYM_EXPORT(tt_lock_alloc_mutex),
ESP_ELFSYM_EXPORT(tt_lock_alloc_for_path),
ESP_ELFSYM_EXPORT(tt_lock_acquire),
ESP_ELFSYM_EXPORT(tt_lock_release),
@ -275,6 +281,12 @@ const esp_elfsym main_symbols[] {
ESP_ELFSYM_EXPORT(tt_lvgl_toolbar_add_switch_action),
ESP_ELFSYM_EXPORT(tt_lvgl_toolbar_add_spinner_action),
ESP_ELFSYM_EXPORT(tt_lvgl_toolbar_clear_actions),
ESP_ELFSYM_EXPORT(tt_message_queue_alloc),
ESP_ELFSYM_EXPORT(tt_message_queue_free),
ESP_ELFSYM_EXPORT(tt_message_queue_put),
ESP_ELFSYM_EXPORT(tt_message_queue_get),
ESP_ELFSYM_EXPORT(tt_message_queue_get_count),
ESP_ELFSYM_EXPORT(tt_message_queue_reset),
ESP_ELFSYM_EXPORT(tt_preferences_alloc),
ESP_ELFSYM_EXPORT(tt_preferences_free),
ESP_ELFSYM_EXPORT(tt_preferences_opt_bool),
@ -283,6 +295,35 @@ const esp_elfsym main_symbols[] {
ESP_ELFSYM_EXPORT(tt_preferences_put_bool),
ESP_ELFSYM_EXPORT(tt_preferences_put_int32),
ESP_ELFSYM_EXPORT(tt_preferences_put_string),
ESP_ELFSYM_EXPORT(tt_semaphore_alloc),
ESP_ELFSYM_EXPORT(tt_semaphore_free),
ESP_ELFSYM_EXPORT(tt_semaphore_acquire),
ESP_ELFSYM_EXPORT(tt_semaphore_release),
ESP_ELFSYM_EXPORT(tt_semaphore_get_count),
ESP_ELFSYM_EXPORT(tt_thread_alloc),
ESP_ELFSYM_EXPORT(tt_thread_alloc_ext),
ESP_ELFSYM_EXPORT(tt_thread_free),
ESP_ELFSYM_EXPORT(tt_thread_set_name),
ESP_ELFSYM_EXPORT(tt_thread_set_stack_size),
ESP_ELFSYM_EXPORT(tt_thread_set_affinity),
ESP_ELFSYM_EXPORT(tt_thread_set_callback),
ESP_ELFSYM_EXPORT(tt_thread_set_priority),
ESP_ELFSYM_EXPORT(tt_thread_set_state_callback),
ESP_ELFSYM_EXPORT(tt_thread_get_state),
ESP_ELFSYM_EXPORT(tt_thread_start),
ESP_ELFSYM_EXPORT(tt_thread_join),
ESP_ELFSYM_EXPORT(tt_thread_get_task_handle),
ESP_ELFSYM_EXPORT(tt_thread_get_return_code),
ESP_ELFSYM_EXPORT(tt_timer_alloc),
ESP_ELFSYM_EXPORT(tt_timer_free),
ESP_ELFSYM_EXPORT(tt_timer_start),
ESP_ELFSYM_EXPORT(tt_timer_reset),
ESP_ELFSYM_EXPORT(tt_timer_reset_with_interval),
ESP_ELFSYM_EXPORT(tt_timer_stop),
ESP_ELFSYM_EXPORT(tt_timer_is_running),
ESP_ELFSYM_EXPORT(tt_timer_get_expiry_time),
ESP_ELFSYM_EXPORT(tt_timer_set_pending_callback),
ESP_ELFSYM_EXPORT(tt_timer_set_thread_priority),
ESP_ELFSYM_EXPORT(tt_timezone_set),
ESP_ELFSYM_EXPORT(tt_timezone_get_name),
ESP_ELFSYM_EXPORT(tt_timezone_get_code),

View File

@ -8,12 +8,27 @@
extern "C" {
LockHandle tt_lock_alloc_mutex(TtMutexType type) {
auto* lock_holder = new LockHolder();
switch (type) {
case MutexTypeNormal:
lock_holder->lock = std::make_shared<tt::Mutex>();
break;
case MutexTypeRecursive:
lock_holder->lock = std::make_shared<tt::RecursiveMutex>();
break;
default:
tt_crash("Type not supported");
}
return lock_holder;
}
LockHandle tt_lock_alloc_for_path(const char* path) {
const auto lock = tt::file::getLock(path);
return new LockHolder(lock);
}
bool tt_lock_acquire(LockHandle handle, TickType_t timeout) {
bool tt_lock_acquire(LockHandle handle, TickType timeout) {
return HANDLE_AS_LOCK(handle)->lock(timeout);
}

View File

@ -1,3 +1,4 @@
#include <tt_kernel.h>
#include <Tactility/lvgl/Lvgl.h>
#include <Tactility/lvgl/LvglSync.h>
@ -15,8 +16,8 @@ void tt_lvgl_stop() {
tt::lvgl::stop();
}
bool tt_lvgl_lock(TickType_t timeout) {
return tt::lvgl::getSyncLock()->lock(timeout);
void tt_lvgl_lock(TickType timeout) {
tt::lvgl::getSyncLock()->lock(timeout);
}
void tt_lvgl_unlock() {

View File

@ -0,0 +1,32 @@
#include "tt_message_queue.h"
#include <Tactility/MessageQueue.h>
#define HANDLE_TO_MESSAGE_QUEUE(handle) ((tt::MessageQueue*)(handle))
extern "C" {
MessageQueueHandle tt_message_queue_alloc(uint32_t capacity, uint32_t messageSize) {
return new tt::MessageQueue(capacity, messageSize);
}
void tt_message_queue_free(MessageQueueHandle handle) {
delete HANDLE_TO_MESSAGE_QUEUE(handle);
}
bool tt_message_queue_put(MessageQueueHandle handle, const void* message, TickType_t timeout) {
return HANDLE_TO_MESSAGE_QUEUE(handle)->put(message, timeout);
}
bool tt_message_queue_get(MessageQueueHandle handle, void* message, TickType_t timeout) {
return HANDLE_TO_MESSAGE_QUEUE(handle)->get(message, timeout);
}
uint32_t tt_message_queue_get_count(MessageQueueHandle handle) {
return HANDLE_TO_MESSAGE_QUEUE(handle)->getCount();
}
void tt_message_queue_reset(MessageQueueHandle handle) {
return HANDLE_TO_MESSAGE_QUEUE(handle)->reset();
}
}

View File

@ -0,0 +1,28 @@
#include "tt_semaphore.h"
#include <Tactility/Semaphore.h>
extern "C" {
#define HANDLE_AS_SEMAPHORE(handle) ((tt::Semaphore*)(handle))
SemaphoreHandle tt_semaphore_alloc(uint32_t maxCount, TickType_t initialCount) {
return new tt::Semaphore(maxCount, initialCount);
}
void tt_semaphore_free(SemaphoreHandle handle) {
delete HANDLE_AS_SEMAPHORE(handle);
}
bool tt_semaphore_acquire(SemaphoreHandle handle, TickType_t timeoutTicks) {
return HANDLE_AS_SEMAPHORE(handle)->acquire(timeoutTicks);
}
bool tt_semaphore_release(SemaphoreHandle handle) {
return HANDLE_AS_SEMAPHORE(handle)->release();
}
uint32_t tt_semaphore_get_count(SemaphoreHandle handle) {
return HANDLE_AS_SEMAPHORE(handle)->getAvailable();
}
}

View File

@ -0,0 +1,77 @@
#include "tt_thread.h"
#include <Tactility/Thread.h>
extern "C" {
#define HANDLE_AS_THREAD(handle) ((tt::Thread*)(handle))
ThreadHandle tt_thread_alloc() {
return new tt::Thread();
}
ThreadHandle tt_thread_alloc_ext(
const char* name,
uint32_t stackSize,
ThreadCallback callback,
void* _Nullable callbackContext
) {
return new tt::Thread(
name,
stackSize,
[callback, callbackContext] {
return callback(callbackContext);
}
);
}
void tt_thread_free(ThreadHandle handle) {
delete HANDLE_AS_THREAD(handle);
}
void tt_thread_set_name(ThreadHandle handle, const char* name) {
HANDLE_AS_THREAD(handle)->setName(name);
}
void tt_thread_set_stack_size(ThreadHandle handle, size_t size) {
HANDLE_AS_THREAD(handle)->setStackSize(size);
}
void tt_thread_set_affinity(ThreadHandle handle, int affinity) {
HANDLE_AS_THREAD(handle)->setAffinity(affinity);
}
void tt_thread_set_callback(ThreadHandle handle, ThreadCallback callback, void* _Nullable callbackContext) {
HANDLE_AS_THREAD(handle)->setMainFunction([callback, callbackContext]() {
return callback(callbackContext);
});
}
void tt_thread_set_priority(ThreadHandle handle, ThreadPriority priority) {
HANDLE_AS_THREAD(handle)->setPriority((tt::Thread::Priority)priority);
}
void tt_thread_set_state_callback(ThreadHandle handle, ThreadStateCallback callback, void* _Nullable callbackContext) {
HANDLE_AS_THREAD(handle)->setStateCallback((tt::Thread::StateCallback)callback, callbackContext);
}
ThreadState tt_thread_get_state(ThreadHandle handle) {
return (ThreadState)HANDLE_AS_THREAD(handle)->getState();
}
void tt_thread_start(ThreadHandle handle) {
HANDLE_AS_THREAD(handle)->start();
}
bool tt_thread_join(ThreadHandle handle, TickType_t timeout) {
return HANDLE_AS_THREAD(handle)->join(timeout);
}
TaskHandle tt_thread_get_task_handle(ThreadHandle handle) {
return HANDLE_AS_THREAD(handle)->getTaskHandle();
}
int32_t tt_thread_get_return_code(ThreadHandle handle) {
return HANDLE_AS_THREAD(handle)->getReturnCode();
}
}

View File

@ -0,0 +1,61 @@
#include "tt_timer.h"
#include <Tactility/Timer.h>
struct TimerWrapper {
std::unique_ptr<tt::Timer> timer;
};
#define HANDLE_TO_WRAPPER(handle) static_cast<TimerWrapper*>(handle)
extern "C" {
TimerHandle tt_timer_alloc(TimerType type, TickType ticks, TimerCallback callback, void* callbackContext) {
auto wrapper = new TimerWrapper;
wrapper->timer = std::make_unique<tt::Timer>(static_cast<tt::Timer::Type>(type), ticks, [callback, callbackContext](){ callback(callbackContext); });
return wrapper;
}
void tt_timer_free(TimerHandle handle) {
auto* wrapper = static_cast<TimerWrapper*>(handle);
wrapper->timer = nullptr;
delete wrapper;
}
bool tt_timer_start(TimerHandle handle) {
return HANDLE_TO_WRAPPER(handle)->timer->start();
}
bool tt_timer_reset(TimerHandle handle) {
return HANDLE_TO_WRAPPER(handle)->timer->reset();
}
bool tt_timer_reset_with_interval(TimerHandle handle, TickType interval) {
return HANDLE_TO_WRAPPER(handle)->timer->reset(interval);
}
bool tt_timer_stop(TimerHandle handle) {
return HANDLE_TO_WRAPPER(handle)->timer->stop();
}
bool tt_timer_is_running(TimerHandle handle) {
return HANDLE_TO_WRAPPER(handle)->timer->isRunning();
}
uint32_t tt_timer_get_expiry_time(TimerHandle handle) {
return HANDLE_TO_WRAPPER(handle)->timer->getExpiryTime();
}
bool tt_timer_set_pending_callback(TimerHandle handle, TimerPendingCallback callback, void* callbackContext, uint32_t callbackArg, TickType_t timeoutTicks) {
return HANDLE_TO_WRAPPER(handle)->timer->setPendingCallback(
callback,
callbackContext,
callbackArg,
timeoutTicks
);
}
void tt_timer_set_thread_priority(TimerHandle handle, ThreadPriority priority) {
HANDLE_TO_WRAPPER(handle)->timer->setCallbackPriority(static_cast<tt::Thread::Priority>(priority));
}
}