Merge develop into main (#313)

- Add app path get() functions to `TactilityC`
- Improved `Dispatcher` and `DispatcherThread`
- Improved `PubSub` (type safety)
- Created test for `DispatcherThread` and `PubSub`
- Save properties files on app exit (various apps) by posting it to the main dispatcher (fixes UI hanging briefly on app exit)
- Fixed bug with `SystemSettings` being read from the wrong file path.
- `loadPropertiesFile()` now uses `file::readLines()` instead of doing that manually
- Increased timer task stack size (required due to issues when reading a properties file for the very first time)
- General cleanup
- Created `EstimatedPower` driver that uses an ADC pin to measure voltage and estimate the battery charge that is left.
- Cleanup of T-Deck board (updated to new style)
This commit is contained in:
Ken Van Hoeylandt
2025-09-01 23:07:00 +02:00
committed by GitHub
parent 5cc5b50694
commit 0f8380e8fe
96 changed files with 766 additions and 682 deletions
+1 -3
View File
@@ -13,9 +13,7 @@ namespace tt {
/**
* A dictionary that maps keys (strings) onto several atomary types.
*/
class Bundle {
private:
class Bundle final {
typedef uint32_t Hash;
+5 -2
View File
@@ -19,7 +19,8 @@ namespace tt {
* Generally, one task would dispatch the execution,
* while the other thread consumes and executes the work.
*/
class Dispatcher {
class Dispatcher final {
public:
typedef std::function<void()> Function;
@@ -38,8 +39,10 @@ public:
/**
* Queue a function to be consumed elsewhere.
* @param[in] function the function to execute elsewhere
* @param[in] timeout lock acquisition timeout
* @return true if dispatching was successful (timeout not reached)
*/
void dispatch(Function function, TickType_t timeout = portMAX_DELAY);
bool dispatch(Function function, TickType_t timeout = portMAX_DELAY);
/**
* Consume 1 or more dispatched function (if any) until the queue is empty.
@@ -5,11 +5,11 @@
namespace tt {
/** Starts a Thread to process dispatched messages */
class DispatcherThread {
class DispatcherThread final {
Dispatcher dispatcher;
std::unique_ptr<Thread> thread;
bool interruptThread = false;
bool interruptThread = true;
int32_t threadMain();
@@ -21,13 +21,16 @@ public:
/**
* Dispatch a message.
*/
void dispatch(Dispatcher::Function function, TickType_t timeout = portMAX_DELAY);
bool dispatch(Dispatcher::Function function, TickType_t timeout = portMAX_DELAY);
/** Start the thread (blocking). */
void start();
/** Stop the thread (blocking). */
void stop();
/** @return true of the thread is started */
bool isStarted() const { return thread != nullptr && !interruptThread; }
};
}
+1 -2
View File
@@ -8,8 +8,7 @@ namespace tt {
/**
* Wrapper for FreeRTOS xEventGroup.
*/
class EventFlag {
private:
class EventFlag final {
struct EventGroupHandleDeleter {
void operator()(EventGroupHandle_t handleToDelete) {
+43 -18
View File
@@ -1,7 +1,3 @@
/**
* @file pubsub.h
* PubSub
*/
#pragma once
#include "Mutex.h"
@@ -9,18 +5,13 @@
namespace tt {
/** PubSub Callback type */
typedef void (*PubSubCallback)(const void* message, void* context);
/** Publish and subscribe to messages in a thread-safe manner. */
class PubSub {
private:
template<typename DataType>
class PubSub final {
struct Subscription {
uint64_t id;
PubSubCallback callback;
void* callbackParameter;
std::function<void(DataType)> callback;
};
typedef std::list<Subscription> Subscriptions;
@@ -42,21 +33,55 @@ public:
/** Start receiving messages at the specified handle (Threadsafe, Re-entrable)
* @param[in] callback
* @param[in] callbackParameter the data to pass to the callback
* @return subscription instance
*/
SubscriptionHandle subscribe(PubSubCallback callback, void* callbackParameter);
SubscriptionHandle subscribe(std::function<void(DataType)> callback) {
mutex.lock();
items.push_back({
.id = (++lastId),
.callback = std::move(callback)
});
mutex.unlock();
return reinterpret_cast<SubscriptionHandle>(lastId);
}
/** Stop receiving messages at the specified handle (Threadsafe, Re-entrable.)
* No use of `tt_pubsub_subscription` allowed after call of this method
* @param[in] subscription
*/
void unsubscribe(SubscriptionHandle subscription);
void unsubscribe(SubscriptionHandle subscription) {
assert(subscription);
/** Publish message to all subscribers (Threadsafe, Re-entrable.)
* @param[in] message message pointer to publish - it is passed as-is to the callback
mutex.lock();
bool result = false;
auto id = reinterpret_cast<uint64_t>(subscription);
for (auto it = items.begin(); it != items.end(); ++it) {
if (it->id == id) {
items.erase(it);
result = true;
break;
}
}
mutex.unlock();
tt_check(result);
}
/** Publish something to all subscribers (Threadsafe, Re-entrable.)
* @param[in] data the data to publish
*/
void publish(void* message);
void publish(DataType data) {
mutex.lock();
// Iterate over subscribers
for (auto& it : items) {
it.callback(data);
}
mutex.unlock();
}
};
@@ -21,8 +21,6 @@ namespace tt {
*/
class Semaphore final : public Lock {
private:
struct SemaphoreHandleDeleter {
void operator()(QueueHandle_t handleToDelete) {
assert(!kernel::isIsr());
@@ -22,9 +22,7 @@ namespace tt {
* interrupt that will write to the buffer (the writer), and only one task or
* interrupt that will read from the buffer (the reader).
*/
class StreamBuffer {
private:
class StreamBuffer final {
struct StreamBufferHandleDeleter {
void operator()(StreamBufferHandle_t handleToDelete) {
+4 -5
View File
@@ -1,6 +1,5 @@
#pragma once
#include "CoreDefines.h"
#include "RtosCompatTask.h"
#include <functional>
@@ -11,7 +10,7 @@ namespace tt {
typedef TaskHandle_t ThreadId;
class Thread {
class Thread final {
public:
@@ -184,8 +183,8 @@ public:
static uint32_t awaitFlags(uint32_t flags, uint32_t options, uint32_t timeout);
};
#define THREAD_PRIORITY_SERVICE Thread::Priority::High
#define THREAD_PRIORITY_RENDER Thread::Priority::Higher
#define THREAD_PRIORITY_ISR Thread::Priority::Critical
constexpr auto THREAD_PRIORITY_SERVICE = Thread::Priority::High;
constexpr auto THREAD_PRIORITY_RENDER = Thread::Priority::Higher;
constexpr auto THREAD_PRIORITY_ISR = Thread::Priority::Critical;
} // namespace