Boot splash and more (#98)

* Boot splash and more

- Added developer sdkconfig
- Refactored the way FreeRTOS includes are included
- Improved Gui/Loader logic
- Implemented boot app with splash screen

* Updated naming for Gui and Loader services

* Renamed Screenshot service methods

* Renames

* Service renames
This commit is contained in:
Ken Van Hoeylandt 2024-11-30 15:37:16 +01:00 committed by GitHub
parent 3f62ec2efa
commit 0188ce721c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
60 changed files with 726 additions and 307 deletions

View File

@ -16,5 +16,16 @@ menu "Tactility App"
bool "M5Stack CoreS3" bool "M5Stack CoreS3"
config TT_BOARD_WAVESHARE_S3_TOUCH config TT_BOARD_WAVESHARE_S3_TOUCH
bool "Waveshare S3 Touch LCD 4.3\"" bool "Waveshare S3 Touch LCD 4.3\""
help
Select a board/hardware configuration.
Use TT_BOARD_CUSTOM if you will manually configure the board in your project.
endchoice endchoice
config TT_SPLASH_DURATION
int "Splash Duration (ms)"
default 1500
range 0 3000
help
The minimum time to show the splash screen in milliseconds.
When set to 0, startup will continue to desktop as soon as boot operations are finished.
endmenu endmenu

View File

@ -9,9 +9,7 @@
#include <esp_lcd_panel_rgb.h> #include <esp_lcd_panel_rgb.h>
#include <esp_timer.h> #include <esp_timer.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include "RtosCompatSemaphore.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#define TAG "waveshare_s3_touch_display" #define TAG "waveshare_s3_touch_display"

View File

@ -1,3 +1,13 @@
## Tactility
The Tactility logo copyrights are owned by Ken Van Hoeylandt.
Firmwares built from [the original repository](https://github.com/ByteWelder/Tactility) can be redistributed with the Tactility logo.
For other usages, [contact me](https://kenvanhoeylandt.net).
The Tactility firmware and code are published under [GPL License Version 3](./LICENSE.md).
# Dependencies
### ESP-IDF ### ESP-IDF
This project uses ESP-IDF to compile the ESP32 firmware. This project uses ESP-IDF to compile the ESP32 firmware.
@ -15,13 +25,12 @@ Website: https://github.com/flipperdevices/flipperzero-firmware/
License: [GPL v3.0](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/LICENSE) License: [GPL v3.0](https://github.com/flipperdevices/flipperzero-firmware/blob/dev/LICENSE)
### Google Fonts ### Google Fonts
Website: https://fonts.google.com/icons Website: https://fonts.google.com/icons
License: [Apache License, version 2.0](https://fonts.google.com/attribution) License: [Apache License, version 2.0](https://fonts.google.com/attribution)
### Components ### Other Components
See `/components` for the respective projects and their licenses. See `/components` for the respective projects and their licenses.

BIN
Data/assets/boot_logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,285 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="800"
height="800"
viewBox="0 0 211.66667 211.66667"
version="1.1"
id="svg1"
inkscape:version="1.4 (e7c3feb100, 2024-10-09)"
sodipodi:docname="Tactility.svg"
inkscape:export-filename="Tactility.png"
inkscape:export-xdpi="96"
inkscape:export-ydpi="96"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:document-units="mm"
inkscape:zoom="1"
inkscape:cx="410.5"
inkscape:cy="336.5"
inkscape:window-width="2115"
inkscape:window-height="1295"
inkscape:window-x="26"
inkscape:window-y="23"
inkscape:window-maximized="0"
inkscape:current-layer="svg1"
showgrid="false" />
<defs
id="defs1">
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect4"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,9.9852864,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect3"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,9.96875,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect2"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,10.022406,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect1"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,10.022406,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect34"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,9.5761962,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect33"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,9.7667784,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect32"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,10.151862,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect31"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,9.8324877,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect30"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,10.269671,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
<inkscape:path-effect
effect="fillet_chamfer"
id="path-effect29"
is_visible="true"
lpeversion="1"
nodesatellites_param="F,0,0,1,0,9.7906096,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1 @ F,0,0,1,0,0,0,1"
radius="0"
unit="px"
method="auto"
mode="F"
chamfer_steps="1"
flexible="false"
use_knot_distance="true"
apply_no_radius="true"
apply_with_radius="true"
only_selected="false"
hide_knots="false" />
</defs>
<g
id="g4"
inkscape:label="Large with textt"
inkscape:export-filename="g4.png"
inkscape:export-xdpi="21.879999"
inkscape:export-ydpi="21.879999">
<g
id="g29"
transform="translate(50,-70)"
inkscape:label="Glyph">
<g
id="g28"
inkscape:label="Upright T">
<path
style="fill:#ffffff;stroke-width:0.289836;paint-order:stroke fill markers"
id="rect26"
width="60"
height="10"
x="10"
y="150"
sodipodi:type="rect"
inkscape:path-effect="#path-effect1"
d="M 20.022406,150 H 70 v 10 H 10 a 10.011209,10.011209 135.06412 0 1 10.022406,-10 z" />
<path
style="fill:#ffffff;stroke-width:0.264583;paint-order:stroke fill markers"
id="rect28"
width="10"
height="60"
x="40"
y="150"
sodipodi:type="rect"
inkscape:path-effect="#path-effect4"
d="m 40,150 h 10 v 60 h -0.01471 A 9.9852864,9.9852864 45 0 1 40,200.01471 Z" />
</g>
<g
id="g28-0"
transform="rotate(180,55,165)"
inkscape:label="Upside-down T">
<path
style="fill:#ffffff;stroke-width:0.289836;paint-order:stroke fill markers"
id="rect26-4"
width="60"
height="10"
x="10"
y="150"
sodipodi:type="rect"
inkscape:path-effect="#path-effect3"
d="M 19.96875,150 H 70 v 10 H 10 v -0.0312 A 9.96875,9.96875 135 0 1 19.96875,150 Z" />
<path
style="fill:#ffffff;stroke-width:0.264583;paint-order:stroke fill markers"
id="rect28-8"
width="10"
height="60"
x="40"
y="150"
sodipodi:type="rect"
inkscape:path-effect="#path-effect2"
d="m 40,150 h 10 v 60 A 10.011209,10.011209 45.064117 0 1 40,199.97759 Z" />
</g>
</g>
<text
xml:space="preserve"
style="font-weight:bold;font-size:16.7003px;font-family:sans-serif;-inkscape-font-specification:'sans-serif Bold';text-align:center;writing-mode:lr-tb;direction:ltr;text-anchor:middle;fill:#ffffff;stroke-width:0.0490925;paint-order:stroke fill markers"
x="104.63994"
y="162.85924"
id="text29"
inkscape:label="Text"><tspan
sodipodi:role="line"
id="tspan29"
style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:16.7003px;font-family:'Source Code Pro';-inkscape-font-specification:'Source Code Pro Bold';stroke-width:0.0490925"
x="104.63994"
y="162.85924">Tactility</tspan></text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.9 KiB

View File

@ -72,6 +72,7 @@ public:
Flags getFlags() const; Flags getFlags() const;
void setFlags(Flags flags); void setFlags(Flags flags);
Flags& mutableFlags() { return flags; }
_Nullable void* getData() const; _Nullable void* getData() const;
void setData(void* data); void setData(void* data);

View File

@ -33,7 +33,7 @@ struct Gui {
}; };
/** Update GUI, request redraw */ /** Update GUI, request redraw */
void request_draw(); void requestDraw();
/** Lock GUI */ /** Lock GUI */
void lock(); void lock();

View File

@ -7,19 +7,50 @@
#include "Thread.h" #include "Thread.h"
#include "service/gui/ViewPort.h" #include "service/gui/ViewPort.h"
#include "service/loader/Loader.h" #include "service/loader/Loader.h"
#include "RtosCompatSemaphore.h"
#include <stack> #include <stack>
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#else
#include "FreeRTOS.h"
#include "semphr.h"
#endif
namespace tt::service::loader { namespace tt::service::loader {
#define APP_STACK_SIZE 32
// region LoaderEvent
typedef enum {
LoaderEventTypeApplicationStarted,
LoaderEventTypeApplicationShowing,
LoaderEventTypeApplicationHiding,
LoaderEventTypeApplicationStopped
} LoaderEventType;
typedef struct {
app::AppInstance& app;
} LoaderEventAppStarted;
typedef struct {
app::AppInstance& app;
} LoaderEventAppShowing;
typedef struct {
app::AppInstance& app;
} LoaderEventAppHiding;
typedef struct {
const app::Manifest& manifest;
} LoaderEventAppStopped;
typedef struct {
LoaderEventType type;
union {
LoaderEventAppStarted app_started;
LoaderEventAppShowing app_showing;
LoaderEventAppHiding app_hiding;
LoaderEventAppStopped app_stopped;
};
} LoaderEvent;
// endregion LoaderEvent
// region LoaderMessage
typedef enum { typedef enum {
LoaderMessageTypeNone, LoaderMessageTypeNone,
@ -104,11 +135,13 @@ public:
} }
}; };
// endregion LoaderMessage
struct Loader { struct Loader {
Thread* thread; Thread* thread;
PubSub* pubsub_internal; PubSub* pubsub_internal;
PubSub* pubsub_external; PubSub* pubsub_external;
MessageQueue queue = MessageQueue(1, sizeof(LoaderMessage)); MessageQueue queue = MessageQueue(2, sizeof(LoaderMessage)); // 2 entries, so you can stop the current app while starting a new one without blocking
Mutex* mutex; Mutex* mutex;
std::stack<app::AppInstance*> app_stack; std::stack<app::AppInstance*> app_stack;
}; };

View File

@ -35,6 +35,7 @@ static const std::vector<const service::Manifest*> system_services = {
// region Default apps // region Default apps
namespace app { namespace app {
namespace boot { extern const Manifest manifest; }
namespace desktop { extern const Manifest manifest; } namespace desktop { extern const Manifest manifest; }
namespace files { extern const Manifest manifest; } namespace files { extern const Manifest manifest; }
namespace gpio { extern const Manifest manifest; } namespace gpio { extern const Manifest manifest; }
@ -57,6 +58,7 @@ extern const app::Manifest screenshot_app;
#endif #endif
static const std::vector<const app::Manifest*> system_apps = { static const std::vector<const app::Manifest*> system_apps = {
&app::boot::manifest,
&app::desktop::manifest, &app::desktop::manifest,
&app::display::manifest, &app::display::manifest,
&app::files::manifest, &app::files::manifest,
@ -145,11 +147,11 @@ void init(const Configuration* config) {
register_user_apps(config->apps); register_user_apps(config->apps);
TT_LOG_I(TAG, "init starting desktop app"); TT_LOG_I(TAG, "init starting desktop app");
service::loader::start_app(app::desktop::manifest.id, true, Bundle()); service::loader::startApp(app::boot::manifest.id, true, Bundle());
if (config->auto_start_app_id) { if (config->auto_start_app_id) {
TT_LOG_I(TAG, "init auto-starting %s", config->auto_start_app_id); TT_LOG_I(TAG, "init auto-starting %s", config->auto_start_app_id);
service::loader::start_app(config->auto_start_app_id, true, Bundle()); service::loader::startApp(config->auto_start_app_id, true, Bundle());
} }
TT_LOG_I(TAG, "init complete"); TT_LOG_I(TAG, "init complete");

View File

@ -12,6 +12,8 @@ namespace tt::app {
class App; class App;
typedef enum { typedef enum {
/** Boot screen, shown before desktop is launched. */
TypeBoot,
/** A desktop app sits at the root of the app stack managed by the Loader service */ /** A desktop app sits at the root of the app stack managed by the Loader service */
TypeDesktop, TypeDesktop,
/** Apps that generally aren't started from the desktop (e.g. image viewer) */ /** Apps that generally aren't started from the desktop (e.g. image viewer) */

View File

@ -0,0 +1,73 @@
#include <Timer.h>
#include <Check.h>
#include <Thread.h>
#include <Kernel.h>
#include "Assets.h"
#include "app/App.h"
#include "lvgl.h"
#include "service/loader/Loader.h"
#include "lvgl/Style.h"
#ifdef ESP_PLATFORM
#include "sdkconfig.h"
#else
#define CONFIG_TT_SPLASH_DURATION 0
#endif
namespace tt::app::boot {
static int32_t threadCallback(void* context);
struct Data {
Data() : thread("", 4096, threadCallback, this) {}
Thread thread;
};
static int32_t threadCallback(TT_UNUSED void* context) {
TickType_t start_time = tt::get_ticks();
// Do stuff
TickType_t end_time = tt::get_ticks();
TickType_t ticks_passed = end_time - start_time;
TickType_t minimum_ticks = (CONFIG_TT_SPLASH_DURATION / portTICK_PERIOD_MS);
if (minimum_ticks > ticks_passed) {
tt::delay_ticks(minimum_ticks - ticks_passed);
}
tt::service::loader::stopApp();
tt::service::loader::startApp("Desktop");
return 0;
}
static void onShow(TT_UNUSED App& app, lv_obj_t* parent) {
Data* data = (Data*)app.getData();
lv_obj_t* image = lv_image_create(parent);
lv_obj_set_size(image, LV_PCT(100), LV_PCT(100));
lv_image_set_src(image, TT_ASSETS_BOOT_LOGO);
lvgl::obj_set_style_bg_blacken(parent);
data->thread.start();
}
static void onStart(App& app) {
Data* data = new Data();
app.setData(data);
}
static void onStop(App& app) {
Data* data = (Data*)app.getData();
data->thread.join();
tt_assert(data);
delete data;
}
extern const Manifest manifest = {
.id = "Boot",
.name = "Boot",
.type = TypeBoot,
.onStart = onStart,
.onStop = onStop,
.onShow = onShow,
};
} // namespace

View File

@ -11,7 +11,7 @@ static void on_app_pressed(lv_event_t* e) {
lv_event_code_t code = lv_event_get_code(e); lv_event_code_t code = lv_event_get_code(e);
if (code == LV_EVENT_CLICKED) { if (code == LV_EVENT_CLICKED) {
const auto* manifest = static_cast<const Manifest*>(lv_event_get_user_data(e)); const auto* manifest = static_cast<const Manifest*>(lv_event_get_user_data(e));
service::loader::start_app(manifest->id, false, Bundle()); service::loader::startApp(manifest->id, false, Bundle());
} }
} }

View File

@ -72,7 +72,7 @@ static void on_navigate_up_pressed(lv_event_t* event) {
} }
static void on_exit_app_pressed(TT_UNUSED lv_event_t* event) { static void on_exit_app_pressed(TT_UNUSED lv_event_t* event) {
service::loader::stop_app(); service::loader::stopApp();
} }
static void view_file(const char* path, const char* filename) { static void view_file(const char* path, const char* filename) {
@ -84,7 +84,7 @@ static void view_file(const char* path, const char* filename) {
// For PC we need to make the path relative to the current work directory, // For PC we need to make the path relative to the current work directory,
// because that's how LVGL maps its 'drive letter' to the file system. // because that's how LVGL maps its 'drive letter' to the file system.
char* processed_filepath; char* processed_filepath;
if (get_platform() == PlatformPc) { if (get_platform() == PlatformSimulator) {
char cwd[PATH_MAX]; char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd)) == nullptr) { if (getcwd(cwd, sizeof(cwd)) == nullptr) {
TT_LOG_E(TAG, "Failed to get current working directory"); TT_LOG_E(TAG, "Failed to get current working directory");
@ -105,7 +105,7 @@ static void view_file(const char* path, const char* filename) {
if (is_supported_image_file(filename)) { if (is_supported_image_file(filename)) {
Bundle bundle; Bundle bundle;
bundle.putString(IMAGE_VIEWER_FILE_ARGUMENT, processed_filepath); bundle.putString(IMAGE_VIEWER_FILE_ARGUMENT, processed_filepath);
service::loader::start_app("ImageViewer", false, bundle); service::loader::startApp("ImageViewer", false, bundle);
} else if (is_supported_text_file(filename)) { } else if (is_supported_text_file(filename)) {
Bundle bundle; Bundle bundle;
if (get_platform() == PlatformEsp) { if (get_platform() == PlatformEsp) {
@ -114,7 +114,7 @@ static void view_file(const char* path, const char* filename) {
// Remove forward slash, because we need a relative path // Remove forward slash, because we need a relative path
bundle.putString(TEXT_VIEWER_FILE_ARGUMENT, processed_filepath + 1); bundle.putString(TEXT_VIEWER_FILE_ARGUMENT, processed_filepath + 1);
} }
service::loader::start_app("TextViewer", false, bundle); service::loader::startApp("TextViewer", false, bundle);
} else { } else {
TT_LOG_W(TAG, "opening files of this type is not supported"); TT_LOG_W(TAG, "opening files of this type is not supported");
} }
@ -199,7 +199,7 @@ static void on_show(App& app, lv_obj_t* parent) {
static void on_start(App& app) { static void on_start(App& app) {
auto* data = data_alloc(); auto* data = data_alloc();
// PC platform is bound to current work directory because of the LVGL file system mapping // PC platform is bound to current work directory because of the LVGL file system mapping
if (get_platform() == PlatformPc) { if (get_platform() == PlatformSimulator) {
char cwd[PATH_MAX]; char cwd[PATH_MAX];
if (getcwd(cwd, sizeof(cwd)) != nullptr) { if (getcwd(cwd, sizeof(cwd)) != nullptr) {
data_set_entries_for_path(data, cwd); data_set_entries_for_path(data, cwd);

View File

@ -12,7 +12,7 @@ namespace tt::app::screenshot {
static void update_mode(ScreenshotUi* ui) { static void update_mode(ScreenshotUi* ui) {
lv_obj_t* label = ui->start_stop_button_label; lv_obj_t* label = ui->start_stop_button_label;
if (service::screenshot::is_started()) { if (service::screenshot::isStarted()) {
lv_label_set_text(label, "Stop"); lv_label_set_text(label, "Stop");
} else { } else {
lv_label_set_text(label, "Start"); lv_label_set_text(label, "Start");
@ -34,7 +34,7 @@ static void on_mode_set(lv_event_t* event) {
static void on_start_pressed(lv_event_t* event) { static void on_start_pressed(lv_event_t* event) {
auto* ui = static_cast<ScreenshotUi*>(lv_event_get_user_data(event)); auto* ui = static_cast<ScreenshotUi*>(lv_event_get_user_data(event));
if (service::screenshot::is_started()) { if (service::screenshot::isStarted()) {
TT_LOG_I(TAG, "Stop screenshot"); TT_LOG_I(TAG, "Stop screenshot");
service::screenshot::stop(); service::screenshot::stop();
} else { } else {
@ -45,13 +45,13 @@ static void on_start_pressed(lv_event_t* event) {
const char* delay_text = lv_textarea_get_text(ui->delay_textarea); const char* delay_text = lv_textarea_get_text(ui->delay_textarea);
int delay = atoi(delay_text); int delay = atoi(delay_text);
if (delay > 0) { if (delay > 0) {
service::screenshot::start_timed(path, delay, 1); service::screenshot::startTimed(path, delay, 1);
} else { } else {
TT_LOG_W(TAG, "Ignored screenshot start because delay was 0"); TT_LOG_W(TAG, "Ignored screenshot start because delay was 0");
} }
} else { } else {
TT_LOG_I(TAG, "Start app screenshots"); TT_LOG_I(TAG, "Start app screenshots");
service::screenshot::start_apps(path); service::screenshot::startApps(path);
} }
} }
@ -73,7 +73,7 @@ static void create_mode_setting_ui(ScreenshotUi* ui, lv_obj_t* parent) {
lv_obj_align_to(mode_dropdown, mode_label, LV_ALIGN_OUT_RIGHT_MID, 8, 0); lv_obj_align_to(mode_dropdown, mode_label, LV_ALIGN_OUT_RIGHT_MID, 8, 0);
lv_obj_add_event_cb(mode_dropdown, on_mode_set, LV_EVENT_VALUE_CHANGED, ui); lv_obj_add_event_cb(mode_dropdown, on_mode_set, LV_EVENT_VALUE_CHANGED, ui);
ui->mode_dropdown = mode_dropdown; ui->mode_dropdown = mode_dropdown;
service::screenshot::ScreenshotMode mode = service::screenshot::get_mode(); service::screenshot::Mode mode = service::screenshot::getMode();
if (mode == service::screenshot::ScreenshotModeApps) { if (mode == service::screenshot::ScreenshotModeApps) {
lv_dropdown_set_selected(mode_dropdown, 1); lv_dropdown_set_selected(mode_dropdown, 1);
} }
@ -168,8 +168,8 @@ void create_ui(const App& app, ScreenshotUi* ui, lv_obj_t* parent) {
create_path_ui(ui, wrapper); create_path_ui(ui, wrapper);
create_timer_settings_ui(ui, wrapper); create_timer_settings_ui(ui, wrapper);
service::gui::keyboard_add_textarea(ui->delay_textarea); service::gui::keyboardAddTextArea(ui->delay_textarea);
service::gui::keyboard_add_textarea(ui->path_textarea); service::gui::keyboardAddTextArea(ui->path_textarea);
update_mode(ui); update_mode(ui);
} }

View File

@ -49,11 +49,11 @@ static void onListItemSelected(lv_event_t* e) {
if (code == LV_EVENT_CLICKED) { if (code == LV_EVENT_CLICKED) {
size_t index = (size_t)(e->user_data); size_t index = (size_t)(e->user_data);
TT_LOG_I(TAG, "Selected item at index %d", index); TT_LOG_I(TAG, "Selected item at index %d", index);
tt::app::App* app = service::loader::get_current_app(); tt::app::App* app = service::loader::getCurrentApp();
Bundle bundle; Bundle bundle;
setResultIndex(bundle, (int32_t)index); setResultIndex(bundle, (int32_t)index);
app->setResult(app::ResultOk, bundle); app->setResult(app::ResultOk, bundle);
service::loader::stop_app(); service::loader::stopApp();
} }
} }
@ -79,12 +79,12 @@ static void onShow(App& app, lv_obj_t* parent) {
if (items.empty() || items.front().empty()) { if (items.empty() || items.front().empty()) {
TT_LOG_E(TAG, "No items provided"); TT_LOG_E(TAG, "No items provided");
app.setResult(ResultError); app.setResult(ResultError);
service::loader::stop_app(); service::loader::stopApp();
} else if (items.size() == 1) { } else if (items.size() == 1) {
Bundle result_bundle; Bundle result_bundle;
setResultIndex(result_bundle, 0); setResultIndex(result_bundle, 0);
app.setResult(ResultOk, result_bundle); app.setResult(ResultOk, result_bundle);
service::loader::stop_app(); service::loader::stopApp();
TT_LOG_W(TAG, "Auto-selecting single item"); TT_LOG_W(TAG, "Auto-selecting single item");
} else { } else {
size_t index = 0; size_t index = 0;
@ -95,7 +95,7 @@ static void onShow(App& app, lv_obj_t* parent) {
} else { } else {
TT_LOG_E(TAG, "No items provided"); TT_LOG_E(TAG, "No items provided");
app.setResult(ResultError); app.setResult(ResultError);
service::loader::stop_app(); service::loader::stopApp();
} }
} }

View File

@ -12,7 +12,7 @@ static void on_app_pressed(lv_event_t* e) {
lv_event_code_t code = lv_event_get_code(e); lv_event_code_t code = lv_event_get_code(e);
if (code == LV_EVENT_CLICKED) { if (code == LV_EVENT_CLICKED) {
const auto* manifest = static_cast<const Manifest*>(lv_event_get_user_data(e)); const auto* manifest = static_cast<const Manifest*>(lv_event_get_user_data(e));
service::loader::start_app(manifest->id, false, Bundle()); service::loader::startApp(manifest->id);
} }
} }

View File

@ -24,7 +24,7 @@ static void on_connect(const service::wifi::settings::WifiApSettings* ap_setting
static WifiConnect* wifi_connect_alloc() { static WifiConnect* wifi_connect_alloc() {
auto* wifi = static_cast<WifiConnect*>(malloc(sizeof(WifiConnect))); auto* wifi = static_cast<WifiConnect*>(malloc(sizeof(WifiConnect)));
PubSub* wifi_pubsub = service::wifi::get_pubsub(); PubSub* wifi_pubsub = service::wifi::getPubsub();
wifi->wifi_subscription = tt_pubsub_subscribe(wifi_pubsub, &event_callback, wifi); wifi->wifi_subscription = tt_pubsub_subscribe(wifi_pubsub, &event_callback, wifi);
wifi->mutex = tt_mutex_alloc(MutexTypeNormal); wifi->mutex = tt_mutex_alloc(MutexTypeNormal);
wifi->state = (WifiConnectState) { wifi->state = (WifiConnectState) {
@ -46,7 +46,7 @@ static WifiConnect* wifi_connect_alloc() {
} }
static void wifi_connect_free(WifiConnect* wifi) { static void wifi_connect_free(WifiConnect* wifi) {
PubSub* wifi_pubsub = service::wifi::get_pubsub(); PubSub* wifi_pubsub = service::wifi::getPubsub();
tt_pubsub_unsubscribe(wifi_pubsub, wifi->wifi_subscription); tt_pubsub_unsubscribe(wifi_pubsub, wifi->wifi_subscription);
tt_mutex_free(wifi->mutex); tt_mutex_free(wifi->mutex);
@ -92,7 +92,7 @@ static void event_callback(const void* message, void* context) {
case service::wifi::WifiEventTypeConnectionSuccess: case service::wifi::WifiEventTypeConnectionSuccess:
if (wifi->state.is_connecting) { if (wifi->state.is_connecting) {
state_set_connecting(wifi, false); state_set_connecting(wifi, false);
service::loader::stop_app(); service::loader::stopApp();
} }
break; break;
default: default:

View File

@ -191,8 +191,8 @@ void view_create(const App& app, void* wifi, lv_obj_t* parent) {
view_create_bottom_buttons(wifi_connect, wrapper); view_create_bottom_buttons(wifi_connect, wrapper);
// Keyboard bindings // Keyboard bindings
service::gui::keyboard_add_textarea(view->ssid_textarea); service::gui::keyboardAddTextArea(view->ssid_textarea);
service::gui::keyboard_add_textarea(view->password_textarea); service::gui::keyboardAddTextArea(view->password_textarea);
// Init from app parameters // Init from app parameters
const Bundle& bundle = app.getParameters(); const Bundle& bundle = app.getParameters();

View File

@ -26,7 +26,7 @@ static void on_connect(const char* ssid) {
Bundle bundle; Bundle bundle;
bundle.putString(WIFI_CONNECT_PARAM_SSID, ssid); bundle.putString(WIFI_CONNECT_PARAM_SSID, ssid);
bundle.putString(WIFI_CONNECT_PARAM_PASSWORD, ""); bundle.putString(WIFI_CONNECT_PARAM_PASSWORD, "");
service::loader::start_app("WifiConnect", false, bundle); service::loader::startApp("WifiConnect", false, bundle);
} }
} }
@ -35,7 +35,7 @@ static void on_disconnect() {
} }
static void on_wifi_toggled(bool enabled) { static void on_wifi_toggled(bool enabled) {
service::wifi::set_enabled(enabled); service::wifi::setEnabled(enabled);
} }
static WifiManage* wifi_manage_alloc() { static WifiManage* wifi_manage_alloc() {
@ -44,8 +44,8 @@ static WifiManage* wifi_manage_alloc() {
wifi->wifi_subscription = nullptr; wifi->wifi_subscription = nullptr;
wifi->mutex = tt_mutex_alloc(MutexTypeNormal); wifi->mutex = tt_mutex_alloc(MutexTypeNormal);
wifi->state = (WifiManageState) { wifi->state = (WifiManageState) {
.scanning = service::wifi::is_scanning(), .scanning = service::wifi::isScanning(),
.radio_state = service::wifi::get_radio_state(), .radio_state = service::wifi::getRadioState(),
.connect_ssid = { 0 }, .connect_ssid = { 0 },
.ap_records = { }, .ap_records = { },
.ap_records_count = 0 .ap_records_count = 0
@ -94,8 +94,8 @@ void request_view_update(WifiManage* wifi) {
static void wifi_manage_event_callback(const void* message, void* context) { static void wifi_manage_event_callback(const void* message, void* context) {
auto* event = (service::wifi::WifiEvent*)message; auto* event = (service::wifi::WifiEvent*)message;
auto* wifi = (WifiManage*)context; auto* wifi = (WifiManage*)context;
TT_LOG_I(TAG, "Update with state %d", service::wifi::get_radio_state()); TT_LOG_I(TAG, "Update with state %d", service::wifi::getRadioState());
state_set_radio_state(wifi, service::wifi::get_radio_state()); state_set_radio_state(wifi, service::wifi::getRadioState());
switch (event->type) { switch (event->type) {
case tt::service::wifi::WifiEventTypeScanStarted: case tt::service::wifi::WifiEventTypeScanStarted:
state_set_scanning(wifi, true); state_set_scanning(wifi, true);
@ -105,7 +105,7 @@ static void wifi_manage_event_callback(const void* message, void* context) {
state_update_scanned_records(wifi); state_update_scanned_records(wifi);
break; break;
case tt::service::wifi::WifiEventTypeRadioStateOn: case tt::service::wifi::WifiEventTypeRadioStateOn:
if (!service::wifi::is_scanning()) { if (!service::wifi::isScanning()) {
service::wifi::scan(); service::wifi::scan();
} }
break; break;
@ -119,12 +119,12 @@ static void wifi_manage_event_callback(const void* message, void* context) {
static void app_show(App& app, lv_obj_t* parent) { static void app_show(App& app, lv_obj_t* parent) {
auto* wifi = (WifiManage*)app.getData(); auto* wifi = (WifiManage*)app.getData();
PubSub* wifi_pubsub = service::wifi::get_pubsub(); PubSub* wifi_pubsub = service::wifi::getPubsub();
wifi->wifi_subscription = tt_pubsub_subscribe(wifi_pubsub, &wifi_manage_event_callback, wifi); wifi->wifi_subscription = tt_pubsub_subscribe(wifi_pubsub, &wifi_manage_event_callback, wifi);
// State update (it has its own locking) // State update (it has its own locking)
state_set_radio_state(wifi, service::wifi::get_radio_state()); state_set_radio_state(wifi, service::wifi::getRadioState());
state_set_scanning(wifi, service::wifi::is_scanning()); state_set_scanning(wifi, service::wifi::isScanning());
state_update_scanned_records(wifi); state_update_scanned_records(wifi);
// View update // View update
@ -135,11 +135,11 @@ static void app_show(App& app, lv_obj_t* parent) {
view_update(&wifi->view, &wifi->bindings, &wifi->state); view_update(&wifi->view, &wifi->bindings, &wifi->state);
unlock(wifi); unlock(wifi);
service::wifi::WifiRadioState radio_state = service::wifi::get_radio_state(); service::wifi::WifiRadioState radio_state = service::wifi::getRadioState();
bool can_scan = radio_state == service::wifi::WIFI_RADIO_ON || bool can_scan = radio_state == service::wifi::WIFI_RADIO_ON ||
radio_state == service::wifi::WIFI_RADIO_CONNECTION_PENDING || radio_state == service::wifi::WIFI_RADIO_CONNECTION_PENDING ||
radio_state == service::wifi::WIFI_RADIO_CONNECTION_ACTIVE; radio_state == service::wifi::WIFI_RADIO_CONNECTION_ACTIVE;
if (can_scan && !service::wifi::is_scanning()) { if (can_scan && !service::wifi::isScanning()) {
service::wifi::scan(); service::wifi::scan();
} }
} }
@ -147,7 +147,7 @@ static void app_show(App& app, lv_obj_t* parent) {
static void app_hide(App& app) { static void app_hide(App& app) {
auto* wifi = (WifiManage*)app.getData(); auto* wifi = (WifiManage*)app.getData();
lock(wifi); lock(wifi);
PubSub* wifi_pubsub = service::wifi::get_pubsub(); PubSub* wifi_pubsub = service::wifi::getPubsub();
tt_pubsub_unsubscribe(wifi_pubsub, wifi->wifi_subscription); tt_pubsub_unsubscribe(wifi_pubsub, wifi->wifi_subscription);
wifi->wifi_subscription = nullptr; wifi->wifi_subscription = nullptr;
wifi->view_enabled = false; wifi->view_enabled = false;

View File

@ -16,7 +16,7 @@ void state_set_radio_state(WifiManage* wifi, service::wifi::WifiRadioState state
void state_update_scanned_records(WifiManage* wifi) { void state_update_scanned_records(WifiManage* wifi) {
lock(wifi); lock(wifi);
service::wifi::get_scan_results( service::wifi::getScanResults(
wifi->state.ap_records, wifi->state.ap_records,
WIFI_SCAN_AP_RECORD_COUNT, WIFI_SCAN_AP_RECORD_COUNT,
&wifi->state.ap_records_count &wifi->state.ap_records_count

View File

@ -43,7 +43,7 @@ static void connect(lv_event_t* event) {
static void create_network_button(WifiManageView* view, WifiManageBindings* bindings, service::wifi::WifiApRecord* record) { static void create_network_button(WifiManageView* view, WifiManageBindings* bindings, service::wifi::WifiApRecord* record) {
const char* ssid = (const char*)record->ssid; const char* ssid = (const char*)record->ssid;
const char* icon = service::statusbar::get_status_icon_for_rssi(record->rssi, record->auth_mode != WIFI_AUTH_OPEN); const char* icon = service::statusbar::getWifiStatusIconForRssi(record->rssi, record->auth_mode != WIFI_AUTH_OPEN);
lv_obj_t* ap_button = lv_list_add_btn( lv_obj_t* ap_button = lv_list_add_btn(
view->networks_list, view->networks_list,
icon, icon,

View File

@ -31,7 +31,7 @@ static const lv_obj_class_t toolbar_class = {
}; };
static void stop_app(TT_UNUSED lv_event_t* event) { static void stop_app(TT_UNUSED lv_event_t* event) {
service::loader::stop_app(); service::loader::stopApp();
} }
static void toolbar_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) { static void toolbar_constructor(const lv_obj_class_t* class_p, lv_obj_t* obj) {

View File

@ -1,14 +1,9 @@
#include "Tactility.h" #include "Tactility.h"
#include "service/gui/Gui_i.h" #include "service/gui/Gui_i.h"
#include "service/loader/Loader.h" #include "service/loader/Loader_i.h"
#include "lvgl/LvglKeypad.h" #include "lvgl/LvglKeypad.h"
#include "lvgl/LvglSync.h" #include "lvgl/LvglSync.h"
#include "RtosCompat.h"
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#else
#include "FreeRTOS.h"
#endif
namespace tt::service::gui { namespace tt::service::gui {
@ -25,9 +20,9 @@ void loader_callback(const void* message, TT_UNUSED void* context) {
if (event->type == loader::LoaderEventTypeApplicationShowing) { if (event->type == loader::LoaderEventTypeApplicationShowing) {
app::App& app = event->app_showing.app; app::App& app = event->app_showing.app;
const app::Manifest& app_manifest = app.getManifest(); const app::Manifest& app_manifest = app.getManifest();
show_app(app, app_manifest.onShow, app_manifest.onHide); showApp(app, app_manifest.onShow, app_manifest.onHide);
} else if (event->type == loader::LoaderEventTypeApplicationHiding) { } else if (event->type == loader::LoaderEventTypeApplicationHiding) {
hide_app(); hideApp();
} }
} }
@ -43,7 +38,7 @@ Gui* gui_alloc() {
); );
instance->mutex = tt_mutex_alloc(MutexTypeRecursive); instance->mutex = tt_mutex_alloc(MutexTypeRecursive);
instance->keyboard = nullptr; instance->keyboard = nullptr;
instance->loader_pubsub_subscription = tt_pubsub_subscribe(loader::get_pubsub(), &loader_callback, instance); instance->loader_pubsub_subscription = tt_pubsub_subscribe(loader::getPubsub(), &loader_callback, instance);
tt_check(lvgl::lock(1000 / portTICK_PERIOD_MS)); tt_check(lvgl::lock(1000 / portTICK_PERIOD_MS));
instance->keyboard_group = lv_group_create(); instance->keyboard_group = lv_group_create();
instance->lvgl_parent = lv_scr_act(); instance->lvgl_parent = lv_scr_act();
@ -76,21 +71,21 @@ void unlock() {
tt_check(tt_mutex_release(gui->mutex) == TtStatusOk); tt_check(tt_mutex_release(gui->mutex) == TtStatusOk);
} }
void request_draw() { void requestDraw() {
tt_assert(gui); tt_assert(gui);
ThreadId thread_id = gui->thread->getId(); ThreadId thread_id = gui->thread->getId();
thread_flags_set(thread_id, GUI_THREAD_FLAG_DRAW); thread_flags_set(thread_id, GUI_THREAD_FLAG_DRAW);
} }
void show_app(app::App& app, ViewPortShowCallback on_show, ViewPortHideCallback on_hide) { void showApp(app::App& app, ViewPortShowCallback on_show, ViewPortHideCallback on_hide) {
lock(); lock();
tt_check(gui->app_view_port == nullptr); tt_check(gui->app_view_port == nullptr);
gui->app_view_port = view_port_alloc(app, on_show, on_hide); gui->app_view_port = view_port_alloc(app, on_show, on_hide);
unlock(); unlock();
request_draw(); requestDraw();
} }
void hide_app() { void hideApp() {
lock(); lock();
ViewPort* view_port = gui->app_view_port; ViewPort* view_port = gui->app_view_port;
tt_check(view_port != nullptr); tt_check(view_port != nullptr);

View File

@ -14,26 +14,26 @@ typedef struct Gui Gui;
* @param on_show * @param on_show
* @param on_hide * @param on_hide
*/ */
void show_app(app::App& app, ViewPortShowCallback on_show, ViewPortHideCallback on_hide); void showApp(app::App& app, ViewPortShowCallback on_show, ViewPortHideCallback on_hide);
/** /**
* Hide the current app's viewport. * Hide the current app's viewport.
* Does not request a re-draw because after hiding the current app, * Does not request a re-draw because after hiding the current app,
* we always show the previous app, and there is always at least 1 app running. * we always show the previous app, and there is always at least 1 app running.
*/ */
void hide_app(); void hideApp();
/** /**
* Show the on-screen keyboard. * Show the on-screen keyboard.
* @param textarea the textarea to focus the input for * @param textarea the textarea to focus the input for
*/ */
void keyboard_show(lv_obj_t* textarea); void keyboardShow(lv_obj_t* textarea);
/** /**
* Hide the on-screen keyboard. * Hide the on-screen keyboard.
* Has no effect when the keyboard is not visible. * Has no effect when the keyboard is not visible.
*/ */
void keyboard_hide(); void keyboardHide();
/** /**
* The on-screen keyboard is only shown when both of these conditions are true: * The on-screen keyboard is only shown when both of these conditions are true:
@ -41,7 +41,7 @@ void keyboard_hide();
* - TT_CONFIG_FORCE_ONSCREEN_KEYBOARD is set to true in tactility_config.h * - TT_CONFIG_FORCE_ONSCREEN_KEYBOARD is set to true in tactility_config.h
* @return if we should show a on-screen keyboard for text input inside our apps * @return if we should show a on-screen keyboard for text input inside our apps
*/ */
bool keyboard_is_enabled(); bool keyboardIsEnabled();
/** /**
* Glue code for the on-screen keyboard and the hardware keyboard: * Glue code for the on-screen keyboard and the hardware keyboard:
@ -49,6 +49,6 @@ bool keyboard_is_enabled();
* - Registers the textarea to the default lv_group_t for hardware keyboards. * - Registers the textarea to the default lv_group_t for hardware keyboards.
* @param textarea * @param textarea
*/ */
void keyboard_add_textarea(lv_obj_t* textarea); void keyboardAddTextArea(lv_obj_t* textarea);
} // namespace } // namespace

View File

@ -28,7 +28,7 @@ static lv_obj_t* create_app_views(Gui* gui, lv_obj_t* parent, app::App& app) {
lv_obj_set_width(child_container, LV_PCT(100)); lv_obj_set_width(child_container, LV_PCT(100));
lv_obj_set_flex_grow(child_container, 1); lv_obj_set_flex_grow(child_container, 1);
if (keyboard_is_enabled()) { if (keyboardIsEnabled()) {
gui->keyboard = lv_keyboard_create(vertical_container); gui->keyboard = lv_keyboard_create(vertical_container);
lv_obj_add_flag(gui->keyboard, LV_OBJ_FLAG_HIDDEN); lv_obj_add_flag(gui->keyboard, LV_OBJ_FLAG_HIDDEN);
} else { } else {

View File

@ -10,19 +10,19 @@ extern Gui* gui;
static void show_keyboard(lv_event_t* event) { static void show_keyboard(lv_event_t* event) {
lv_obj_t* target = lv_event_get_current_target_obj(event); lv_obj_t* target = lv_event_get_current_target_obj(event);
keyboard_show(target); keyboardShow(target);
lv_obj_scroll_to_view(target, LV_ANIM_ON); lv_obj_scroll_to_view(target, LV_ANIM_ON);
} }
static void hide_keyboard(TT_UNUSED lv_event_t* event) { static void hide_keyboard(TT_UNUSED lv_event_t* event) {
keyboard_hide(); keyboardHide();
} }
bool keyboard_is_enabled() { bool keyboardIsEnabled() {
return !lvgl::keypad_is_available() || TT_CONFIG_FORCE_ONSCREEN_KEYBOARD; return !lvgl::keypad_is_available() || TT_CONFIG_FORCE_ONSCREEN_KEYBOARD;
} }
void keyboard_show(lv_obj_t* textarea) { void keyboardShow(lv_obj_t* textarea) {
lock(); lock();
if (gui->keyboard) { if (gui->keyboard) {
@ -33,7 +33,7 @@ void keyboard_show(lv_obj_t* textarea) {
unlock(); unlock();
} }
void keyboard_hide() { void keyboardHide() {
lock(); lock();
if (gui->keyboard) { if (gui->keyboard) {
@ -43,11 +43,11 @@ void keyboard_hide() {
unlock(); unlock();
} }
void keyboard_add_textarea(lv_obj_t* textarea) { void keyboardAddTextArea(lv_obj_t* textarea) {
lock(); lock();
tt_check(lvgl::lock(0), "lvgl should already be locked before calling this method"); tt_check(lvgl::lock(0), "lvgl should already be locked before calling this method");
if (keyboard_is_enabled()) { if (keyboardIsEnabled()) {
lv_obj_add_event_cb(textarea, show_keyboard, LV_EVENT_FOCUSED, nullptr); lv_obj_add_event_cb(textarea, show_keyboard, LV_EVENT_FOCUSED, nullptr);
lv_obj_add_event_cb(textarea, hide_keyboard, LV_EVENT_DEFOCUSED, nullptr); lv_obj_add_event_cb(textarea, hide_keyboard, LV_EVENT_DEFOCUSED, nullptr);
lv_obj_add_event_cb(textarea, hide_keyboard, LV_EVENT_READY, nullptr); lv_obj_add_event_cb(textarea, hide_keyboard, LV_EVENT_READY, nullptr);

View File

@ -5,14 +5,12 @@
#include "service/Manifest.h" #include "service/Manifest.h"
#include "service/gui/Gui.h" #include "service/gui/Gui.h"
#include "service/loader/Loader_i.h" #include "service/loader/Loader_i.h"
#include "RtosCompat.h"
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
#include "esp_heap_caps.h" #include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h"
#else #else
#include "FreeRTOS.h"
#include "lvgl/LvglSync.h" #include "lvgl/LvglSync.h"
#endif #endif
namespace tt::service::loader { namespace tt::service::loader {
@ -65,7 +63,7 @@ static void loader_unlock() {
tt_check(tt_mutex_release(loader_singleton->mutex) == TtStatusOk); tt_check(tt_mutex_release(loader_singleton->mutex) == TtStatusOk);
} }
LoaderStatus start_app(const std::string& id, bool blocking, const Bundle& bundle) { LoaderStatus startApp(const std::string& id, bool blocking, const Bundle& arguments) {
TT_LOG_I(TAG, "Start app %s", id.c_str()); TT_LOG_I(TAG, "Start app %s", id.c_str());
tt_assert(loader_singleton); tt_assert(loader_singleton);
@ -73,7 +71,7 @@ LoaderStatus start_app(const std::string& id, bool blocking, const Bundle& bundl
.value = LoaderStatusOk .value = LoaderStatusOk
}; };
auto* start_message = new LoaderMessageAppStart(id, bundle); auto* start_message = new LoaderMessageAppStart(id, arguments);
LoaderMessage message(start_message, result); LoaderMessage message(start_message, result);
EventFlag* event_flag = blocking ? new EventFlag() : nullptr; EventFlag* event_flag = blocking ? new EventFlag() : nullptr;
@ -94,14 +92,14 @@ LoaderStatus start_app(const std::string& id, bool blocking, const Bundle& bundl
return result.value; return result.value;
} }
void stop_app() { void stopApp() {
TT_LOG_I(TAG, "Stop app"); TT_LOG_I(TAG, "Stop app");
tt_check(loader_singleton); tt_check(loader_singleton);
LoaderMessage message(LoaderMessageTypeAppStop); LoaderMessage message(LoaderMessageTypeAppStop);
loader_singleton->queue.put(&message, TtWaitForever); loader_singleton->queue.put(&message, TtWaitForever);
} }
app::App* _Nullable get_current_app() { app::App* _Nullable getCurrentApp() {
tt_assert(loader_singleton); tt_assert(loader_singleton);
loader_lock(); loader_lock();
app::AppInstance* app = loader_singleton->app_stack.top(); app::AppInstance* app = loader_singleton->app_stack.top();
@ -109,7 +107,7 @@ app::App* _Nullable get_current_app() {
return dynamic_cast<app::App*>(app); return dynamic_cast<app::App*>(app);
} }
PubSub* get_pubsub() { PubSub* getPubsub() {
tt_assert(loader_singleton); tt_assert(loader_singleton);
// it's safe to return pubsub without locking // it's safe to return pubsub without locking
// because it's never freed and loader is never exited // because it's never freed and loader is never exited
@ -160,7 +158,7 @@ static void app_transition_to_state(app::AppInstance& app, app::State state) {
LoaderEvent event_showing = { LoaderEvent event_showing = {
.type = LoaderEventTypeApplicationShowing, .type = LoaderEventTypeApplicationShowing,
.app_showing = { .app_showing = {
.app = dynamic_cast<app::App&>(app) .app = app
} }
}; };
tt_pubsub_publish(loader_singleton->pubsub_external, &event_showing); tt_pubsub_publish(loader_singleton->pubsub_external, &event_showing);
@ -171,7 +169,7 @@ static void app_transition_to_state(app::AppInstance& app, app::State state) {
LoaderEvent event_hiding = { LoaderEvent event_hiding = {
.type = LoaderEventTypeApplicationHiding, .type = LoaderEventTypeApplicationHiding,
.app_hiding = { .app_hiding = {
.app = dynamic_cast<app::App&>(app) .app = app
} }
}; };
tt_pubsub_publish(loader_singleton->pubsub_external, &event_hiding); tt_pubsub_publish(loader_singleton->pubsub_external, &event_hiding);
@ -198,6 +196,8 @@ static LoaderStatus loader_do_start_app_with_manifest(
auto previous_app = !loader_singleton->app_stack.empty() ? loader_singleton->app_stack.top() : nullptr; auto previous_app = !loader_singleton->app_stack.empty() ? loader_singleton->app_stack.top() : nullptr;
auto new_app = new app::AppInstance(*manifest, bundle); auto new_app = new app::AppInstance(*manifest, bundle);
new_app->mutableFlags().showStatusbar = (manifest->type != app::TypeBoot);
loader_singleton->app_stack.push(new_app); loader_singleton->app_stack.push(new_app);
app_transition_to_state(*new_app, app::StateInitial); app_transition_to_state(*new_app, app::StateInitial);
app_transition_to_state(*new_app, app::StateStarted); app_transition_to_state(*new_app, app::StateStarted);
@ -217,7 +217,7 @@ static LoaderStatus loader_do_start_app_with_manifest(
LoaderEvent event_external = { LoaderEvent event_external = {
.type = LoaderEventTypeApplicationStarted, .type = LoaderEventTypeApplicationStarted,
.app_started = { .app_started = {
.app = dynamic_cast<app::App&>(*new_app) .app = *new_app
} }
}; };
tt_pubsub_publish(loader_singleton->pubsub_external, &event_external); tt_pubsub_publish(loader_singleton->pubsub_external, &event_external);
@ -233,6 +233,7 @@ static LoaderStatus do_start_by_id(
const app::Manifest* manifest = app::findAppById(id); const app::Manifest* manifest = app::findAppById(id);
if (manifest == nullptr) { if (manifest == nullptr) {
TT_LOG_E(TAG, "App not found: %s", id.c_str());
return LoaderStatusErrorUnknownApp; return LoaderStatusErrorUnknownApp;
} else { } else {
return loader_do_start_app_with_manifest(manifest, bundle); return loader_do_start_app_with_manifest(manifest, bundle);
@ -251,14 +252,15 @@ static void do_stop_app() {
return; return;
} }
if (original_stack_size == 1) { // Stop current app
app::AppInstance* app_to_stop = loader_singleton->app_stack.top();
if (original_stack_size == 1 && app_to_stop->getManifest().type != app::TypeBoot) {
loader_unlock(); loader_unlock();
TT_LOG_E(TAG, "Stop app: can't stop root app"); TT_LOG_E(TAG, "Stop app: can't stop root app");
return; return;
} }
// Stop current app
app::AppInstance* app_to_stop = loader_singleton->app_stack.top();
std::unique_ptr<app::ResultHolder> result_holder = std::move(app_to_stop->getResult()); std::unique_ptr<app::ResultHolder> result_holder = std::move(app_to_stop->getResult());
const app::Manifest& manifest = app_to_stop->getManifest(); const app::Manifest& manifest = app_to_stop->getManifest();
@ -272,35 +274,38 @@ static void do_stop_app() {
TT_LOG_I(TAG, "Free heap: %zu", heap_caps_get_free_size(MALLOC_CAP_INTERNAL)); TT_LOG_I(TAG, "Free heap: %zu", heap_caps_get_free_size(MALLOC_CAP_INTERNAL));
#endif #endif
app::AppInstance* app_to_resume = loader_singleton->app_stack.top(); // If there's a previous app, resume it
tt_assert(app_to_resume); if (!loader_singleton->app_stack.empty()) {
app_transition_to_state(*app_to_resume, app::StateShowing); app::AppInstance* app_to_resume = loader_singleton->app_stack.top();
tt_assert(app_to_resume);
app_transition_to_state(*app_to_resume, app::StateShowing);
auto on_result = app_to_resume->getManifest().onResult; auto on_result = app_to_resume->getManifest().onResult;
if (on_result != nullptr) { if (on_result != nullptr) {
if (result_holder != nullptr) { if (result_holder != nullptr) {
Bundle* result_bundle = result_holder->resultData; Bundle* result_bundle = result_holder->resultData;
if (result_bundle != nullptr) { if (result_bundle != nullptr) {
on_result( on_result(
*app_to_resume, *app_to_resume,
result_holder->result, result_holder->result,
*result_bundle *result_bundle
); );
} else {
const Bundle empty_bundle;
on_result(
*app_to_resume,
result_holder->result,
empty_bundle
);
}
} else { } else {
const Bundle empty_bundle; const Bundle empty_bundle;
on_result( on_result(
*app_to_resume, *app_to_resume,
result_holder->result, app::ResultCancelled,
empty_bundle empty_bundle
); );
} }
} else {
const Bundle empty_bundle;
on_result(
*app_to_resume,
app::ResultCancelled,
empty_bundle
);
} }
} }

View File

@ -16,58 +16,26 @@ typedef enum {
LoaderStatusErrorInternal, LoaderStatusErrorInternal,
} LoaderStatus; } LoaderStatus;
typedef enum {
LoaderEventTypeApplicationStarted,
LoaderEventTypeApplicationShowing,
LoaderEventTypeApplicationHiding,
LoaderEventTypeApplicationStopped
} LoaderEventType;
typedef struct {
app::App& app;
} LoaderEventAppStarted;
typedef struct {
app::App& app;
} LoaderEventAppShowing;
typedef struct {
app::App& app;
} LoaderEventAppHiding;
typedef struct {
const app::Manifest& manifest;
} LoaderEventAppStopped;
typedef struct {
LoaderEventType type;
union {
LoaderEventAppStarted app_started;
LoaderEventAppShowing app_showing;
LoaderEventAppHiding app_hiding;
LoaderEventAppStopped app_stopped;
};
} LoaderEvent;
/** /**
* @brief Start an app * @brief Start an app
* @param[in] id application name or id * @param[in] id application name or id
* @param[in] blocking application arguments * @param[in] blocking whether this call is blocking or not. You cannot call this from an LVGL thread.
* @param[in] bundle optional bundle. Ownership is transferred to Loader. * @param[in] arguments optional parameters to pass onto the application
* @return LoaderStatus * @return LoaderStatus
*/ */
LoaderStatus start_app(const std::string& id, bool blocking, const Bundle& bundle); LoaderStatus startApp(const std::string& id, bool blocking = false, const Bundle& arguments = Bundle());
/** /**
* @brief Stop the currently showing app. Show the previous app if any app was still running. * @brief Stop the currently showing app. Show the previous app if any app was still running.
*/ */
void stop_app(); void stopApp();
app::App* _Nullable get_current_app(); app::App* _Nullable getCurrentApp();
/** /**
* @brief PubSub for LoaderEvent * @brief PubSub for LoaderEvent
*/ */
PubSub* get_pubsub(); PubSub* getPubsub();
} // namespace } // namespace

View File

@ -15,8 +15,8 @@ extern const Manifest manifest;
typedef struct { typedef struct {
Mutex* mutex; Mutex* mutex;
ScreenshotTask* task; task::ScreenshotTask* task;
ScreenshotMode mode; Mode mode;
} ServiceData; } ServiceData;
static ServiceData* service_data_alloc() { static ServiceData* service_data_alloc() {
@ -49,14 +49,14 @@ static void on_start(Service& service) {
static void on_stop(Service& service) { static void on_stop(Service& service) {
auto* data = static_cast<ServiceData*>(service.getData()); auto* data = static_cast<ServiceData*>(service.getData());
if (data->task) { if (data->task) {
task_free(data->task); task::free(data->task);
data->task = nullptr; data->task = nullptr;
} }
tt_mutex_free(data->mutex); tt_mutex_free(data->mutex);
service_data_free(data); service_data_free(data);
} }
void start_apps(const char* path) { void startApps(const char* path) {
_Nullable auto* service = findServiceById(manifest.id); _Nullable auto* service = findServiceById(manifest.id);
if (service == nullptr) { if (service == nullptr) {
TT_LOG_E(TAG, "Service not found"); TT_LOG_E(TAG, "Service not found");
@ -66,16 +66,16 @@ void start_apps(const char* path) {
auto* data = static_cast<ServiceData*>(service->getData()); auto* data = static_cast<ServiceData*>(service->getData());
service_data_lock(data); service_data_lock(data);
if (data->task == nullptr) { if (data->task == nullptr) {
data->task = task_alloc(); data->task = task::alloc();
data->mode = ScreenshotModeApps; data->mode = ScreenshotModeApps;
task_start_apps(data->task, path); task::startApps(data->task, path);
} else { } else {
TT_LOG_E(TAG, "Screenshot task already running"); TT_LOG_E(TAG, "Screenshot task already running");
} }
service_data_unlock(data); service_data_unlock(data);
} }
void start_timed(const char* path, uint8_t delay_in_seconds, uint8_t amount) { void startTimed(const char* path, uint8_t delay_in_seconds, uint8_t amount) {
_Nullable auto* service = findServiceById(manifest.id); _Nullable auto* service = findServiceById(manifest.id);
if (service == nullptr) { if (service == nullptr) {
TT_LOG_E(TAG, "Service not found"); TT_LOG_E(TAG, "Service not found");
@ -85,9 +85,9 @@ void start_timed(const char* path, uint8_t delay_in_seconds, uint8_t amount) {
auto* data = static_cast<ServiceData*>(service->getData()); auto* data = static_cast<ServiceData*>(service->getData());
service_data_lock(data); service_data_lock(data);
if (data->task == nullptr) { if (data->task == nullptr) {
data->task = task_alloc(); data->task = task::alloc();
data->mode = ScreenshotModeTimed; data->mode = ScreenshotModeTimed;
task_start_timed(data->task, path, delay_in_seconds, amount); task::startTimed(data->task, path, delay_in_seconds, amount);
} else { } else {
TT_LOG_E(TAG, "Screenshot task already running"); TT_LOG_E(TAG, "Screenshot task already running");
} }
@ -104,8 +104,8 @@ void stop() {
auto data = static_cast<ServiceData*>(service->getData()); auto data = static_cast<ServiceData*>(service->getData());
service_data_lock(data); service_data_lock(data);
if (data->task != nullptr) { if (data->task != nullptr) {
task_stop(data->task); task::stop(data->task);
task_free(data->task); task::free(data->task);
data->task = nullptr; data->task = nullptr;
data->mode = ScreenshotModeNone; data->mode = ScreenshotModeNone;
} else { } else {
@ -114,7 +114,7 @@ void stop() {
service_data_unlock(data); service_data_unlock(data);
} }
ScreenshotMode get_mode() { Mode getMode() {
_Nullable auto* service = findServiceById(manifest.id); _Nullable auto* service = findServiceById(manifest.id);
if (service == nullptr) { if (service == nullptr) {
TT_LOG_E(TAG, "Service not found"); TT_LOG_E(TAG, "Service not found");
@ -122,14 +122,14 @@ ScreenshotMode get_mode() {
} else { } else {
auto* data = static_cast<ServiceData*>(service->getData()); auto* data = static_cast<ServiceData*>(service->getData());
service_data_lock(data); service_data_lock(data);
ScreenshotMode mode = data->mode; Mode mode = data->mode;
service_data_unlock(data); service_data_unlock(data);
return mode; return mode;
} }
} }
bool is_started() { bool isStarted() {
return get_mode() != ScreenshotModeNone; return getMode() != ScreenshotModeNone;
} }
extern const Manifest manifest = { extern const Manifest manifest = {

View File

@ -8,24 +8,24 @@ typedef enum {
ScreenshotModeNone, ScreenshotModeNone,
ScreenshotModeTimed, ScreenshotModeTimed,
ScreenshotModeApps ScreenshotModeApps
} ScreenshotMode; } Mode;
/** @brief Starts taking screenshot with a timer /** @brief Starts taking screenshot with a timer
* @param path the path to store the screenshots in * @param path the path to store the screenshots in
* @param delay_in_seconds the delay before starting (and between successive screenshots) * @param delay_in_seconds the delay before starting (and between successive screenshots)
* @param amount 0 = indefinite, >0 for a specific * @param amount 0 = indefinite, >0 for a specific
*/ */
void start_timed(const char* path, uint8_t delay_in_seconds, uint8_t amount); void startTimed(const char* path, uint8_t delay_in_seconds, uint8_t amount);
/** @brief Starts taking screenshot when an app is started /** @brief Starts taking screenshot when an app is started
* @param path the path to store the screenshots in * @param path the path to store the screenshots in
*/ */
void start_apps(const char* path); void startApps(const char* path);
void stop(); void stop();
ScreenshotMode get_mode(); Mode getMode();
bool is_started(); bool isStarted();
} // namespace } // namespace

View File

@ -8,7 +8,7 @@
#include "service/loader/Loader.h" #include "service/loader/Loader.h"
#include "lvgl/LvglSync.h" #include "lvgl/LvglSync.h"
namespace tt::service::screenshot { namespace tt::service::screenshot::task {
#define TAG "screenshot_task" #define TAG "screenshot_task"
@ -39,7 +39,7 @@ static void task_unlock(ScreenshotTaskData* data) {
tt_check(tt_mutex_release(data->mutex) == TtStatusOk); tt_check(tt_mutex_release(data->mutex) == TtStatusOk);
} }
ScreenshotTask* task_alloc() { ScreenshotTask* alloc() {
auto* data = static_cast<ScreenshotTaskData*>(malloc(sizeof(ScreenshotTaskData))); auto* data = static_cast<ScreenshotTaskData*>(malloc(sizeof(ScreenshotTaskData)));
*data = (ScreenshotTaskData) { *data = (ScreenshotTaskData) {
.thread = nullptr, .thread = nullptr,
@ -49,10 +49,10 @@ ScreenshotTask* task_alloc() {
return data; return data;
} }
void task_free(ScreenshotTask* task) { void free(ScreenshotTask* task) {
auto* data = static_cast<ScreenshotTaskData*>(task); auto* data = static_cast<ScreenshotTaskData*>(task);
if (data->thread) { if (data->thread) {
task_stop(data); stop(data);
} }
} }
@ -98,7 +98,7 @@ static int32_t screenshot_task(void* context) {
break; // Interrupted loop break; // Interrupted loop
} }
} else if (data->work.type == TASK_WORK_TYPE_APPS) { } else if (data->work.type == TASK_WORK_TYPE_APPS) {
app::App* _Nullable app = loader::get_current_app(); app::App* _Nullable app = loader::getCurrentApp();
if (app) { if (app) {
const app::Manifest& manifest = app->getManifest(); const app::Manifest& manifest = app->getManifest();
if (manifest.id != last_app_id) { if (manifest.id != last_app_id) {
@ -136,7 +136,7 @@ static void task_start(ScreenshotTaskData* data) {
task_unlock(data); task_unlock(data);
} }
void task_start_apps(ScreenshotTask* task, const char* path) { void startApps(ScreenshotTask* task, const char* path) {
tt_check(strlen(path) < (SCREENSHOT_PATH_LIMIT - 1)); tt_check(strlen(path) < (SCREENSHOT_PATH_LIMIT - 1));
auto* data = static_cast<ScreenshotTaskData*>(task); auto* data = static_cast<ScreenshotTaskData*>(task);
task_lock(data); task_lock(data);
@ -151,7 +151,7 @@ void task_start_apps(ScreenshotTask* task, const char* path) {
task_unlock(data); task_unlock(data);
} }
void task_start_timed(ScreenshotTask* task, const char* path, uint8_t delay_in_seconds, uint8_t amount) { void startTimed(ScreenshotTask* task, const char* path, uint8_t delay_in_seconds, uint8_t amount) {
tt_check(strlen(path) < (SCREENSHOT_PATH_LIMIT - 1)); tt_check(strlen(path) < (SCREENSHOT_PATH_LIMIT - 1));
auto* data = static_cast<ScreenshotTaskData*>(task); auto* data = static_cast<ScreenshotTaskData*>(task);
task_lock(data); task_lock(data);
@ -168,7 +168,7 @@ void task_start_timed(ScreenshotTask* task, const char* path, uint8_t delay_in_s
task_unlock(data); task_unlock(data);
} }
void task_stop(ScreenshotTask* task) { void stop(ScreenshotTask* task) {
auto* data = static_cast<ScreenshotTaskData*>(task); auto* data = static_cast<ScreenshotTaskData*>(task);
if (data->thread != nullptr) { if (data->thread != nullptr) {
task_lock(data); task_lock(data);

View File

@ -2,13 +2,13 @@
#include <cstdint> #include <cstdint>
namespace tt::service::screenshot { namespace tt::service::screenshot::task {
typedef void ScreenshotTask; typedef void ScreenshotTask;
ScreenshotTask* task_alloc(); ScreenshotTask* alloc();
void task_free(ScreenshotTask* task); void free(ScreenshotTask* task);
/** @brief Start taking screenshots after a certain delay /** @brief Start taking screenshots after a certain delay
* @param task the screenshot task * @param task the screenshot task
@ -16,17 +16,17 @@ void task_free(ScreenshotTask* task);
* @param delay_in_seconds the delay before starting (and between successive screenshots) * @param delay_in_seconds the delay before starting (and between successive screenshots)
* @param amount 0 = indefinite, >0 for a specific * @param amount 0 = indefinite, >0 for a specific
*/ */
void task_start_timed(ScreenshotTask* task, const char* path, uint8_t delay_in_seconds, uint8_t amount); void startTimed(ScreenshotTask* task, const char* path, uint8_t delay_in_seconds, uint8_t amount);
/** @brief Start taking screenshot whenever an app is started /** @brief Start taking screenshot whenever an app is started
* @param task the screenshot task * @param task the screenshot task
* @param path the path to store the screenshots at * @param path the path to store the screenshots at
*/ */
void task_start_apps(ScreenshotTask* task, const char* path); void startApps(ScreenshotTask* task, const char* path);
/** @brief Stop taking screenshots /** @brief Stop taking screenshots
* @param task the screenshot task * @param task the screenshot task
*/ */
void task_stop(ScreenshotTask* task); void stop(ScreenshotTask* task);
} }

View File

@ -25,7 +25,7 @@ typedef struct {
// region wifi // region wifi
const char* get_status_icon_for_rssi(int rssi, bool secured) { const char* getWifiStatusIconForRssi(int rssi, bool secured) {
if (rssi > 0) { if (rssi > 0) {
return TT_ASSETS_ICON_WIFI_CONNECTION_ISSUE; return TT_ASSETS_ICON_WIFI_CONNECTION_ISSUE;
} else if (rssi >= -30) { } else if (rssi >= -30) {
@ -52,16 +52,16 @@ static const char* wifi_get_status_icon(wifi::WifiRadioState state, bool secure)
case wifi::WIFI_RADIO_CONNECTION_PENDING: case wifi::WIFI_RADIO_CONNECTION_PENDING:
return TT_ASSETS_ICON_WIFI_FIND; return TT_ASSETS_ICON_WIFI_FIND;
case wifi::WIFI_RADIO_CONNECTION_ACTIVE: case wifi::WIFI_RADIO_CONNECTION_ACTIVE:
rssi = wifi::get_rssi(); rssi = wifi::getRssi();
return get_status_icon_for_rssi(rssi, secure); return getWifiStatusIconForRssi(rssi, secure);
default: default:
tt_crash("not implemented"); tt_crash("not implemented");
} }
} }
static void update_wifi_icon(ServiceData* data) { static void update_wifi_icon(ServiceData* data) {
wifi::WifiRadioState radio_state = wifi::get_radio_state(); wifi::WifiRadioState radio_state = wifi::getRadioState();
bool is_secure = wifi::is_connection_secure(); bool is_secure = wifi::isConnectionSecure();
const char* desired_icon = wifi_get_status_icon(radio_state, is_secure); const char* desired_icon = wifi_get_status_icon(radio_state, is_secure);
if (data->wifi_last_icon != desired_icon) { if (data->wifi_last_icon != desired_icon) {
lvgl::statusbar_icon_set_image(data->wifi_icon_id, desired_icon); lvgl::statusbar_icon_set_image(data->wifi_icon_id, desired_icon);

View File

@ -8,6 +8,6 @@ namespace tt::service::statusbar {
* @param secured whether the access point is a secured one (as in: not an open one) * @param secured whether the access point is a secured one (as in: not an open one)
* @return * @return
*/ */
const char* get_status_icon_for_rssi(int rssi, bool secured); const char* getWifiStatusIconForRssi(int rssi, bool secured);
} // namespace } // namespace

View File

@ -2,14 +2,7 @@
#include "CoreDefines.h" #include "CoreDefines.h"
#include "Log.h" #include "Log.h"
#include "RtosCompatTask.h"
#ifdef ESP_TARGET
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#else
#include "FreeRTOS.h"
#include "task.h"
#endif
#define TAG "kernel" #define TAG "kernel"

View File

@ -1,14 +1,7 @@
#pragma once #pragma once
#include "CoreTypes.h" #include "CoreTypes.h"
#include "RtosCompatEventGroups.h"
#ifdef ESP_TARGET
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#else
#include "FreeRTOS.h"
#include "event_groups.h"
#endif
namespace tt { namespace tt {

View File

@ -2,14 +2,7 @@
#include "Check.h" #include "Check.h"
#include "CoreDefines.h" #include "CoreDefines.h"
#include "CoreTypes.h" #include "CoreTypes.h"
#include "RtosCompatTask.h"
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#else
#include "FreeRTOS.h"
#include "task.h"
#endif
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
#include "rom/ets_sys.h" #include "rom/ets_sys.h"
@ -118,7 +111,7 @@ uint32_t kernel_get_tick_frequency() {
return (configTICK_RATE_HZ); return (configTICK_RATE_HZ);
} }
void delay_tick(uint32_t ticks) { void delay_ticks(TickType_t ticks) {
tt_assert(!kernel_is_irq()); tt_assert(!kernel_is_irq());
if (ticks == 0U) { if (ticks == 0U) {
taskYIELD(); taskYIELD();
@ -127,7 +120,7 @@ void delay_tick(uint32_t ticks) {
} }
} }
TtStatus delay_until_tick(uint32_t tick) { TtStatus delay_until_tick(TickType_t tick) {
tt_assert(!kernel_is_irq()); tt_assert(!kernel_is_irq());
TickType_t tcnt, delay; TickType_t tcnt, delay;
@ -154,7 +147,7 @@ TtStatus delay_until_tick(uint32_t tick) {
return (stat); return (stat);
} }
uint32_t get_tick() { TickType_t get_ticks() {
TickType_t ticks; TickType_t ticks;
if (kernel_is_irq() != 0U) { if (kernel_is_irq() != 0U) {
@ -166,11 +159,11 @@ uint32_t get_tick() {
return ticks; return ticks;
} }
uint32_t ms_to_ticks(uint32_t milliseconds) { TickType_t ms_to_ticks(uint32_t milliseconds) {
#if configTICK_RATE_HZ == 1000 #if configTICK_RATE_HZ == 1000
return milliseconds; return (TickType_t)milliseconds;
#else #else
return (uint32_t)((float)configTICK_RATE_HZ) / 1000.0f * (float)milliseconds; return (TickType_t)((float)configTICK_RATE_HZ) / 1000.0f * (float)milliseconds;
#endif #endif
} }
@ -182,7 +175,7 @@ void delay_ms(uint32_t milliseconds) {
#if configTICK_RATE_HZ_RAW == 1000 #if configTICK_RATE_HZ_RAW == 1000
tt_delay_tick(milliseconds); tt_delay_tick(milliseconds);
#else #else
delay_tick(ms_to_ticks(milliseconds)); delay_ticks(ms_to_ticks(milliseconds));
#endif #endif
} else if (milliseconds > 0) { } else if (milliseconds > 0) {
delay_us(milliseconds * 1000); delay_us(milliseconds * 1000);
@ -201,7 +194,7 @@ Platform get_platform() {
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
return PlatformEsp; return PlatformEsp;
#else #else
return PlatformPc; return PlatformSimulator;
#endif #endif
} }

View File

@ -2,11 +2,17 @@
#include "CoreTypes.h" #include "CoreTypes.h"
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#else
#include "FreeRTOS.h"
#endif
namespace tt { namespace tt {
typedef enum { typedef enum {
PlatformEsp, PlatformEsp,
PlatformPc PlatformSimulator
} Platform; } Platform;
/** Check if CPU is in IRQ or kernel running and IRQ is masked /** Check if CPU is in IRQ or kernel running and IRQ is masked
@ -64,6 +70,8 @@ int32_t kernel_restore_lock(int32_t lock);
*/ */
uint32_t kernel_get_tick_frequency(); uint32_t kernel_get_tick_frequency();
TickType_t get_ticks();
/** Delay execution /** Delay execution
* *
* @warning This should never be called in interrupt request context. * @warning This should never be called in interrupt request context.
@ -72,7 +80,7 @@ uint32_t kernel_get_tick_frequency();
* *
* @param[in] ticks The ticks count to pause * @param[in] ticks The ticks count to pause
*/ */
void delay_tick(uint32_t ticks); void delay_ticks(TickType_t ticks);
/** Delay until tick /** Delay until tick
* *
@ -89,7 +97,7 @@ TtStatus delay_until_tick(uint32_t tick);
* @param[in] milliseconds time in milliseconds * @param[in] milliseconds time in milliseconds
* @return time in ticks * @return time in ticks
*/ */
uint32_t ms_to_ticks(uint32_t milliseconds); TickType_t ms_to_ticks(uint32_t milliseconds);
/** Delay in milliseconds /** Delay in milliseconds
* *

View File

@ -6,14 +6,7 @@
#include "CoreTypes.h" #include "CoreTypes.h"
#include "Thread.h" #include "Thread.h"
#include "RtosCompatSemaphore.h"
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#else
#include "FreeRTOS.h"
#include "semphr.h"
#endif
namespace tt { namespace tt {

View File

@ -0,0 +1,13 @@
#pragma once
/**
* Compatibility includes for FreeRTOS.
* Custom FreeRTOS from ESP-IDF prefixes paths with "freertos/",
* but this isn't the normal behaviour for the regular FreeRTOS project.
*/
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#else
#include "FreeRTOS.h"
#endif

View File

@ -0,0 +1,14 @@
#pragma once
/**
* See explanation in RtosCompat.h
*/
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#include "freertos/event_groups.h"
#else
#include "FreeRTOS.h"
#include "event_groups.h"
#endif

View File

@ -0,0 +1,14 @@
#pragma once
/**
* See explanation in RtosCompat.h
*/
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#else
#include "FreeRTOS.h"
#include "semphr.h"
#endif

View File

@ -0,0 +1,14 @@
#pragma once
/**
* See explanation in RtosCompat.h
*/
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#else
#include "FreeRTOS.h"
#include "task.h"
#endif

View File

@ -0,0 +1,13 @@
#pragma once
/**
* See explanation in RtosCompat.h
*/
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
#else
#include "FreeRTOS.h"
#include "timers.h"
#endif

View File

@ -1,6 +1,7 @@
#include "Timer.h" #include "Timer.h"
#include "Check.h" #include "Check.h"
#include "Kernel.h" #include "Kernel.h"
#include "RtosCompat.h"
namespace tt { namespace tt {
@ -73,7 +74,7 @@ uint32_t Timer::getExpireTime() {
return (uint32_t)xTimerGetExpiryTime(timerHandle); return (uint32_t)xTimerGetExpiryTime(timerHandle);
} }
void Timer::pendingCallback(PendigCallback callback, void* callbackContext, uint32_t arg) { void Timer::pendingCallback(PendingCallback callback, void* callbackContext, uint32_t arg) {
BaseType_t ret = pdFAIL; BaseType_t ret = pdFAIL;
if (kernel_is_irq()) { if (kernel_is_irq()) {
ret = xTimerPendFunctionCallFromISR(callback, callbackContext, arg, nullptr); ret = xTimerPendFunctionCallFromISR(callback, callbackContext, arg, nullptr);

View File

@ -2,24 +2,17 @@
#include "CoreTypes.h" #include "CoreTypes.h"
#ifdef ESP_PLATFORM #include "RtosCompatTimers.h"
#include "freertos/FreeRTOS.h"
#include "freertos/timers.h"
#else
#include "FreeRTOS.h"
#include "timers.h"
#endif
namespace tt { namespace tt {
class Timer { class Timer {
private: private:
TimerHandle_t timerHandle; TimerHandle_t timerHandle;
public: public:
typedef void (*Callback)(void* context); typedef void (*Callback)(void* context);
typedef void (*PendigCallback)(void* context, uint32_t arg); typedef void (*PendingCallback)(void* context, uint32_t arg);
Callback callback; Callback callback;
@ -88,7 +81,7 @@ public:
*/ */
uint32_t getExpireTime(); uint32_t getExpireTime();
void pendingCallback(PendigCallback callback, void* callbackContext, uint32_t arg); void pendingCallback(PendingCallback callback, void* callbackContext, uint32_t arg);
typedef enum { typedef enum {
TimerThreadPriorityNormal, /**< Lower then other threads */ TimerThreadPriorityNormal, /**< Lower then other threads */
@ -102,9 +95,4 @@ public:
void setThreadPriority(TimerThreadPriority priority); void setThreadPriority(TimerThreadPriority priority);
}; };
} // namespace } // namespace

View File

@ -1,13 +1,6 @@
#include "Critical.h" #include "Critical.h"
#include "CoreDefines.h" #include "CoreDefines.h"
#include "RtosCompatTask.h"
#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#else
#include "FreeRTOS.h"
#include "task.h"
#endif
#ifdef ESP_PLATFORM #ifdef ESP_PLATFORM
static portMUX_TYPE critical_mutex; static portMUX_TYPE critical_mutex;

View File

@ -3,6 +3,9 @@
#define TT_ASSET_FOLDER "A:/assets/" #define TT_ASSET_FOLDER "A:/assets/"
#define TT_ASSET(file) TT_ASSET_FOLDER file #define TT_ASSET(file) TT_ASSET_FOLDER file
// Splash
#define TT_ASSETS_BOOT_LOGO TT_ASSET("boot_logo.png")
// App icons // App icons
#define TT_ASSETS_APP_ICON_FALLBACK TT_ASSET("app_icon_fallback.png") #define TT_ASSETS_APP_ICON_FALLBACK TT_ASSET("app_icon_fallback.png")
#define TT_ASSETS_APP_ICON_FILES TT_ASSET("app_icon_files.png") #define TT_ASSETS_APP_ICON_FILES TT_ASSET("app_icon_files.png")

View File

@ -2,16 +2,11 @@
#include "I2cCompat.h" #include "I2cCompat.h"
#include "CoreTypes.h" #include "CoreTypes.h"
#include "RtosCompat.h"
#include <climits> #include <climits>
#include <string> #include <string>
#include <vector> #include <vector>
#ifdef ESP_TARGET
#include "freertos/FreeRTOS.h"
#else
#include "FreeRTOS.h"
#endif
namespace tt::hal::i2c { namespace tt::hal::i2c {
typedef enum { typedef enum {

View File

@ -74,9 +74,9 @@ typedef struct {
* @brief Get wifi pubsub * @brief Get wifi pubsub
* @return PubSub* * @return PubSub*
*/ */
PubSub* get_pubsub(); PubSub* getPubsub();
WifiRadioState get_radio_state(); WifiRadioState getRadioState();
/** /**
* @brief Request scanning update. Returns immediately. Results are through pubsub. * @brief Request scanning update. Returns immediately. Results are through pubsub.
*/ */
@ -85,26 +85,26 @@ void scan();
/** /**
* @return true if wifi is actively scanning * @return true if wifi is actively scanning
*/ */
bool is_scanning(); bool isScanning();
/** /**
* @brief Returns the access points from the last scan (if any). It only contains public APs. * @brief Returns the access points from the last scan (if any). It only contains public APs.
* @param records the allocated buffer to store the records in * @param records the allocated buffer to store the records in
* @param limit the maximum amount of records to store * @param limit the maximum amount of records to store
*/ */
void get_scan_results(WifiApRecord records[], uint16_t limit, uint16_t* result_count); void getScanResults(WifiApRecord records[], uint16_t limit, uint16_t* result_count);
/** /**
* @brief Overrides the default scan result size of 16. * @brief Overrides the default scan result size of 16.
* @param records the record limit for the scan result (84 bytes per record!) * @param records the record limit for the scan result (84 bytes per record!)
*/ */
void set_scan_records(uint16_t records); void setScanRecords(uint16_t records);
/** /**
* @brief Enable/disable the radio. Ignores input if desired state matches current state. * @brief Enable/disable the radio. Ignores input if desired state matches current state.
* @param enabled * @param enabled
*/ */
void set_enabled(bool enabled); void setEnabled(bool enabled);
/** /**
* @brief Connect to a network. Disconnects any existing connection. * @brief Connect to a network. Disconnects any existing connection.
@ -121,11 +121,11 @@ void disconnect();
/** /**
* Return true if the connection isn't unencrypted. * Return true if the connection isn't unencrypted.
*/ */
bool is_connection_secure(); bool isConnectionSecure();
/** /**
* Returns the RSSI value (negative number) or return 1 when not connected * Returns the RSSI value (negative number) or return 1 when not connected
*/ */
int get_rssi(); int getRssi();
} // namespace } // namespace

View File

@ -99,12 +99,12 @@ Wifi::~Wifi() {
// region Public functions // region Public functions
PubSub* get_pubsub() { PubSub* getPubsub() {
tt_assert(wifi_singleton); tt_assert(wifi_singleton);
return wifi_singleton->pubsub; return wifi_singleton->pubsub;
} }
WifiRadioState get_radio_state() { WifiRadioState getRadioState() {
tt_assert(wifi_singleton); tt_assert(wifi_singleton);
lock(wifi_singleton); lock(wifi_singleton);
WifiRadioState state = wifi_singleton->radio_state; WifiRadioState state = wifi_singleton->radio_state;
@ -121,7 +121,7 @@ void scan() {
unlock(wifi_singleton); unlock(wifi_singleton);
} }
bool is_scanning() { bool isScanning() {
tt_assert(wifi_singleton); tt_assert(wifi_singleton);
lock(wifi_singleton); lock(wifi_singleton);
bool is_scanning = wifi_singleton->scan_active; bool is_scanning = wifi_singleton->scan_active;
@ -152,7 +152,7 @@ void disconnect() {
unlock(wifi_singleton); unlock(wifi_singleton);
} }
void set_scan_records(uint16_t records) { void setScanRecords(uint16_t records) {
tt_assert(wifi_singleton); tt_assert(wifi_singleton);
lock(wifi_singleton); lock(wifi_singleton);
if (records != wifi_singleton->scan_list_limit) { if (records != wifi_singleton->scan_list_limit) {
@ -162,7 +162,7 @@ void set_scan_records(uint16_t records) {
unlock(wifi_singleton); unlock(wifi_singleton);
} }
void get_scan_results(WifiApRecord records[], uint16_t limit, uint16_t* result_count) { void getScanResults(WifiApRecord records[], uint16_t limit, uint16_t* result_count) {
tt_assert(wifi_singleton); tt_assert(wifi_singleton);
tt_assert(result_count); tt_assert(result_count);
@ -185,7 +185,7 @@ void get_scan_results(WifiApRecord records[], uint16_t limit, uint16_t* result_c
unlock(wifi_singleton); unlock(wifi_singleton);
} }
void set_enabled(bool enabled) { void setEnabled(bool enabled) {
tt_assert(wifi_singleton); tt_assert(wifi_singleton);
lock(wifi_singleton); lock(wifi_singleton);
if (enabled) { if (enabled) {
@ -200,7 +200,7 @@ void set_enabled(bool enabled) {
unlock(wifi_singleton); unlock(wifi_singleton);
} }
bool is_connection_secure() { bool isConnectionSecure() {
tt_assert(wifi_singleton); tt_assert(wifi_singleton);
lock(wifi_singleton); lock(wifi_singleton);
bool is_secure = wifi_singleton->secure_connection; bool is_secure = wifi_singleton->secure_connection;
@ -208,7 +208,7 @@ bool is_connection_secure() {
return is_secure; return is_secure;
} }
int get_rssi() { int getRssi() {
tt_assert(wifi_singleton); tt_assert(wifi_singleton);
static int rssi = 0; static int rssi = 0;
if (esp_wifi_sta_get_rssi(&rssi) == ESP_OK) { if (esp_wifi_sta_get_rssi(&rssi) == ESP_OK) {

View File

@ -67,12 +67,12 @@ static void wifi_free(Wifi* instance) {
// region Public functions // region Public functions
PubSub* get_pubsub() { PubSub* getPubsub() {
tt_assert(wifi); tt_assert(wifi);
return wifi->pubsub; return wifi->pubsub;
} }
WifiRadioState get_radio_state() { WifiRadioState getRadioState() {
return wifi->radio_state; return wifi->radio_state;
} }
@ -81,7 +81,7 @@ void scan() {
wifi->scan_active = false; // TODO: enable and then later disable automatically wifi->scan_active = false; // TODO: enable and then later disable automatically
} }
bool is_scanning() { bool isScanning() {
tt_assert(wifi); tt_assert(wifi);
return wifi->scan_active; return wifi->scan_active;
} }
@ -95,12 +95,12 @@ void disconnect() {
tt_assert(wifi); tt_assert(wifi);
} }
void set_scan_records(uint16_t records) { void setScanRecords(uint16_t records) {
tt_assert(wifi); tt_assert(wifi);
// TODO: implement // TODO: implement
} }
void get_scan_results(WifiApRecord records[], uint16_t limit, uint16_t* result_count) { void getScanResults(WifiApRecord records[], uint16_t limit, uint16_t* result_count) {
tt_check(wifi); tt_check(wifi);
tt_check(result_count); tt_check(result_count);
@ -126,7 +126,7 @@ void get_scan_results(WifiApRecord records[], uint16_t limit, uint16_t* result_c
} }
} }
void set_enabled(bool enabled) { void setEnabled(bool enabled) {
tt_assert(wifi != NULL); tt_assert(wifi != NULL);
if (enabled) { if (enabled) {
wifi->radio_state = WIFI_RADIO_ON; wifi->radio_state = WIFI_RADIO_ON;
@ -136,11 +136,11 @@ void set_enabled(bool enabled) {
} }
} }
bool is_connection_secure() { bool isConnectionSecure() {
return wifi->secure_connection; return wifi->secure_connection;
} }
int get_rssi() { int getRssi() {
if (wifi->radio_state == WIFI_RADIO_CONNECTION_ACTIVE) { if (wifi->radio_state == WIFI_RADIO_CONNECTION_ACTIVE) {
return -30; return -30;
} else { } else {

View File

@ -14,7 +14,7 @@ TEST_CASE("dispatcher should not call callback if consume isn't called") {
uint32_t counter = 0; uint32_t counter = 0;
dispatcher.dispatch(&increment_callback, &counter); dispatcher.dispatch(&increment_callback, &counter);
delay_tick(10); delay_ticks(10);
CHECK_EQ(counter, 0); CHECK_EQ(counter, 0);
} }

View File

@ -18,7 +18,7 @@ TEST_CASE("a timer passes the context correctly") {
int foo = 1; int foo = 1;
auto* timer = new Timer(Timer::TypeOnce, &timer_callback_with_context, &foo); auto* timer = new Timer(Timer::TypeOnce, &timer_callback_with_context, &foo);
timer->start(1); timer->start(1);
delay_tick(10); delay_ticks(10);
timer->stop(); timer->stop();
delete timer; delete timer;
@ -29,10 +29,10 @@ TEST_CASE("TimerTypePeriodic timers can be stopped and restarted") {
int counter = 0; int counter = 0;
auto* timer = new Timer(Timer::TypePeriodic, &timer_callback_with_counter, &counter); auto* timer = new Timer(Timer::TypePeriodic, &timer_callback_with_counter, &counter);
timer->start(1); timer->start(1);
delay_tick(10); delay_ticks(10);
timer->stop(); timer->stop();
timer->start(1); timer->start(1);
delay_tick(10); delay_ticks(10);
timer->stop(); timer->stop();
delete timer; delete timer;
@ -44,7 +44,7 @@ TEST_CASE("TimerTypePeriodic calls the callback periodically") {
int ticks_to_run = 10; int ticks_to_run = 10;
auto* timer = new Timer(Timer::TypePeriodic, &timer_callback_with_counter, &counter); auto* timer = new Timer(Timer::TypePeriodic, &timer_callback_with_counter, &counter);
timer->start(1); timer->start(1);
delay_tick(ticks_to_run); delay_ticks(ticks_to_run);
timer->stop(); timer->stop();
delete timer; delete timer;
@ -55,10 +55,10 @@ TEST_CASE("restarting TimerTypeOnce timers calls the callback again") {
int counter = 0; int counter = 0;
auto* timer = new Timer(Timer::TypeOnce, &timer_callback_with_counter, &counter); auto* timer = new Timer(Timer::TypeOnce, &timer_callback_with_counter, &counter);
timer->start(1); timer->start(1);
delay_tick(10); delay_ticks(10);
timer->stop(); timer->stop();
timer->start(1); timer->start(1);
delay_tick(10); delay_ticks(10);
timer->stop(); timer->stop();
delete timer; delete timer;

View File

@ -13,6 +13,7 @@ CONFIG_FREERTOS_HZ=1000
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2 CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
CONFIG_FREERTOS_SMP=n CONFIG_FREERTOS_SMP=n
CONFIG_FREERTOS_UNICORE=n CONFIG_FREERTOS_UNICORE=n
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@ -13,7 +13,7 @@ CONFIG_FREERTOS_HZ=1000
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2 CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
CONFIG_FREERTOS_SMP=n CONFIG_FREERTOS_SMP=n
CONFIG_FREERTOS_UNICORE=n CONFIG_FREERTOS_UNICORE=n
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
@ -25,6 +25,7 @@ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_FLASHMODE_QIO=y CONFIG_FLASHMODE_QIO=y
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
# Hardware: SPI RAM # Hardware: SPI RAM
CONFIG_SPIRAM=y CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_OCT=y CONFIG_SPIRAM_MODE_OCT=y

View File

@ -13,7 +13,7 @@ CONFIG_FREERTOS_HZ=1000
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2 CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
CONFIG_FREERTOS_SMP=n CONFIG_FREERTOS_SMP=n
CONFIG_FREERTOS_UNICORE=n CONFIG_FREERTOS_UNICORE=n
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"
@ -25,6 +25,7 @@ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y
CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y
CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y
CONFIG_FLASHMODE_QIO=y CONFIG_FLASHMODE_QIO=y
CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH=y
# Hardware: SPI RAM # Hardware: SPI RAM
CONFIG_SPIRAM=y CONFIG_SPIRAM=y
CONFIG_SPIRAM_MODE_QUAD=y CONFIG_SPIRAM_MODE_QUAD=y

View File

@ -13,6 +13,7 @@ CONFIG_FREERTOS_HZ=1000
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2 CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
CONFIG_FREERTOS_SMP=n CONFIG_FREERTOS_SMP=n
CONFIG_FREERTOS_UNICORE=n CONFIG_FREERTOS_UNICORE=n
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

View File

@ -13,6 +13,7 @@ CONFIG_FREERTOS_HZ=1000
CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2 CONFIG_FREERTOS_TASK_NOTIFICATION_ARRAY_ENTRIES=2
CONFIG_FREERTOS_SMP=n CONFIG_FREERTOS_SMP=n
CONFIG_FREERTOS_UNICORE=n CONFIG_FREERTOS_UNICORE=n
CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH=4096
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="partitions.csv"

4
sdkconfig.developer Normal file
View File

@ -0,0 +1,4 @@
CONFIG_STACK_CHECK_STRONG=y
LV_USE_SYSMON=y
CONFIG_LV_USE_OBSERVER=y
CONFIG_LV_USE_PERF_MONITOR=y