@geastack/core 0.1.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +36 -0
- package/app_frame_perf.cpp +77 -0
- package/css.d.ts +1 -0
- package/events.cpp +67 -0
- package/gea_app_entry.cpp +317 -0
- package/gea_sources.mjs +126 -0
- package/gea_sources.sh +36 -0
- package/include/app.h +60 -0
- package/include/apps.h +46 -0
- package/include/audio.h +90 -0
- package/include/ble.h +212 -0
- package/include/bluetooth/hid_profile.h +92 -0
- package/include/camera.h +107 -0
- package/include/canvas.h +290 -0
- package/include/display.h +390 -0
- package/include/display_present.h +869 -0
- package/include/event.h +32 -0
- package/include/events.h +116 -0
- package/include/gea/embedded.h +13 -0
- package/include/gea/reactive_runtime.h +32 -0
- package/include/gea.h +14 -0
- package/include/gea_perf_config.h +96 -0
- package/include/geaos/abi.h +165 -0
- package/include/geolocation.h +126 -0
- package/include/gpio.h +61 -0
- package/include/graphics/font.h +122 -0
- package/include/i2c.h +20 -0
- package/include/image.h +156 -0
- package/include/imu.h +23 -0
- package/include/input.h +33 -0
- package/include/memory.h +52 -0
- package/include/pixel.h +907 -0
- package/include/platform/file_cache.h +18 -0
- package/include/power.h +11 -0
- package/include/runtime.h +83 -0
- package/include/services/app_runner.h +10 -0
- package/include/services/app_state.h +14 -0
- package/include/services/battery_service.h +12 -0
- package/include/services/bluetooth_service.h +13 -0
- package/include/services/diagnostics.h +76 -0
- package/include/services/diagnostics_platform.h +54 -0
- package/include/services/frame_scheduler.h +71 -0
- package/include/services/mirror.h +49 -0
- package/include/services/network_services.h +25 -0
- package/include/services/ota.h +32 -0
- package/include/services/runtime_log.h +11 -0
- package/include/services/storage_service.h +26 -0
- package/include/touch.h +38 -0
- package/include/ui/signal.h +149 -0
- package/include/wifi.h +67 -0
- package/index.d.ts +1940 -0
- package/jsx.d.ts +1 -0
- package/package.json +70 -0
- package/runtime/ble.ts +49 -0
- package/runtime/color.ts +21 -0
- package/runtime/compiler.ts +43 -0
- package/runtime/host.ts +1083 -0
- package/runtime/images.ts +129 -0
- package/runtime/primitives.ts +49 -0
- package/runtime-surface.ts +180 -0
- package/runtime.cpp +431 -0
- package/runtime.ts +34 -0
- package/scripts/build-gea-vite-geatsc.mjs +4514 -0
- package/scripts/dotenv-defines.mjs +98 -0
- package/scripts/gea-bundle-type-hints.mjs +546 -0
- package/scripts/gea-embedded-compat-staging.mjs +17 -0
- package/scripts/gea-embedded-compat-transform.mjs +427 -0
- package/scripts/gea-vite-module-graph-plugin.mjs +578 -0
- package/scripts/generate-gea-embedded-assets.mjs +296 -0
- package/scripts/generate-gea-embedded-fonts.mjs +1252 -0
- package/scripts/generate-installed-app-plan.mjs +55 -0
- package/scripts/native-object-cache.sh +244 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
namespace gea::platform::storage {
|
|
4
|
+
|
|
5
|
+
// Ensure the persistent file-cache filesystem is mounted; returns true when a
|
|
6
|
+
// writable root is available. Calls the registered mount provider (idempotent —
|
|
7
|
+
// safe on every file op). With no provider registered it returns false, so
|
|
8
|
+
// targets without persistent storage transparently fall back to no caching.
|
|
9
|
+
bool ensureMounted();
|
|
10
|
+
|
|
11
|
+
// Register the platform's mount provider. A target with persistent storage (e.g.
|
|
12
|
+
// a microSD card) calls this at startup with its mount function. Done via
|
|
13
|
+
// explicit registration rather than a weak symbol so the provider's translation
|
|
14
|
+
// unit is guaranteed to be linked in (see the waveshare-p4-7 sdcard_mount.cpp,
|
|
15
|
+
// wired from app_main).
|
|
16
|
+
void setMountProvider(bool (*provider)());
|
|
17
|
+
|
|
18
|
+
} // namespace gea::platform::storage
|
package/include/power.h
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
// Optional application boot hook. An app that ships native sources can define
|
|
4
|
+
// `gea_app_native_boot` to bring its own hardware up before the runtime claims
|
|
5
|
+
// the display, the radios and the frame loop. It is a weak *declaration* with
|
|
6
|
+
// no default definition: an app that does not provide one leaves the symbol
|
|
7
|
+
// null and Runtime::run() skips the call.
|
|
8
|
+
extern "C" void gea_app_native_boot(void) __attribute__((weak));
|
|
9
|
+
|
|
10
|
+
// Bytes of internal, DMA-capable RAM to hold back for the display across the
|
|
11
|
+
// app's native boot hook. The app hook runs FIRST, by design -- an app that owns
|
|
12
|
+
// hardware needs its large contiguous internal allocations before the panel
|
|
13
|
+
// takes what is left -- but an app that fills internal RAM leaves the display
|
|
14
|
+
// unable to bring its bus up at all: the failure this exists for was 3,236 bytes
|
|
15
|
+
// free, largest block 1,600, and "SPI bus init failed: ESP_ERR_NO_MEM" one
|
|
16
|
+
// millisecond after the framebuffer landed in PSRAM. So Runtime::boot() takes a
|
|
17
|
+
// reserve through gea::platform::memory::Memory before the hook and releases it
|
|
18
|
+
// immediately before Display::init(), which turns an out-of-memory panel into
|
|
19
|
+
// the app giving up its last few kilobytes. 0 disables the reserve, which is
|
|
20
|
+
// every board that has never needed it. Declare it with `gea.defines`.
|
|
21
|
+
//
|
|
22
|
+
// Reserving for the WHOLE hook is the blunt version, and it is wrong for an app
|
|
23
|
+
// whose hook has a mandatory phase and a greedy one. The pedal is the case: its
|
|
24
|
+
// model arenas are a 213,472-byte bin-packing problem against 217,592 free, and
|
|
25
|
+
// holding anything back there makes the packer fail or time out, while the
|
|
26
|
+
// reverb promotion that runs straight afterwards takes 13 KB purely because it
|
|
27
|
+
// is there. Such an app leaves this at 0 and calls holdDisplayReserve() itself,
|
|
28
|
+
// between the two phases. See that method.
|
|
29
|
+
// A board that declares neither a panel nor a canvas has nothing to render to.
|
|
30
|
+
// The runtime then builds no framebuffer, no app tree and no frame loop; the
|
|
31
|
+
// board's own boot hook still runs, so a headless appliance keeps everything
|
|
32
|
+
// that is not the UI. Boards that say nothing keep a display, as they always
|
|
33
|
+
// have.
|
|
34
|
+
#ifndef GEA_EMBEDDED_NO_DISPLAY
|
|
35
|
+
#define GEA_EMBEDDED_NO_DISPLAY 0
|
|
36
|
+
#endif
|
|
37
|
+
|
|
38
|
+
#ifndef GEA_EMBEDDED_DISPLAY_INTERNAL_RESERVE_BYTES
|
|
39
|
+
#define GEA_EMBEDDED_DISPLAY_INTERNAL_RESERVE_BYTES 0
|
|
40
|
+
#endif
|
|
41
|
+
|
|
42
|
+
namespace gea::framework {
|
|
43
|
+
|
|
44
|
+
struct RuntimeOptions {
|
|
45
|
+
int width = 0;
|
|
46
|
+
int height = 0;
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
class Runtime {
|
|
50
|
+
public:
|
|
51
|
+
static void run(const RuntimeOptions &options);
|
|
52
|
+
// Runs the app's native boot hook, once. run() calls this itself, so an app
|
|
53
|
+
// never has to; a target calls it first when it wants the hook to run on a
|
|
54
|
+
// different task than the frame loop. That is not a stylistic choice: the
|
|
55
|
+
// hook is where an app initialises flash-backed things (NVS, a filesystem,
|
|
56
|
+
// its own partitions), and a task that performs a flash operation must be on
|
|
57
|
+
// an internal stack, while a frame loop that only renders can live on an
|
|
58
|
+
// external one. A target that keeps the loop on a PSRAM stack therefore runs
|
|
59
|
+
// the hook on the bring-up task and hands the loop over afterwards.
|
|
60
|
+
static void runNativeBoot();
|
|
61
|
+
|
|
62
|
+
// Bring-up only: services, storage, radios, display, the app's first mount,
|
|
63
|
+
// the frame scheduler -- everything up to but not including the event loop.
|
|
64
|
+
// It touches flash, so it must run on a task whose stack is in INTERNAL RAM;
|
|
65
|
+
// a target that runs the loop on an external stack calls this from its
|
|
66
|
+
// bring-up task and then lets run() do nothing but loop. Idempotent: run()
|
|
67
|
+
// calls it, so a target that does not care never sees a difference.
|
|
68
|
+
static bool boot(const RuntimeOptions &options);
|
|
69
|
+
|
|
70
|
+
// Hands the runtime a block of internal RAM to hold for the display and free
|
|
71
|
+
// immediately before Display::init(). For an app whose native boot hook has
|
|
72
|
+
// a phase that must not see less RAM than it actually has, followed by one
|
|
73
|
+
// that will opportunistically eat whatever is left: take the block with
|
|
74
|
+
// gea::platform::memory::Memory::reserveInternalDma() at the moment in
|
|
75
|
+
// between and pass it here. nullptr is accepted and means no reserve, so a
|
|
76
|
+
// failed reservation needs no check at the call site. Called more than once,
|
|
77
|
+
// the later block is held and the earlier one is freed at once -- the
|
|
78
|
+
// runtime holds exactly one app reserve, in addition to the one
|
|
79
|
+
// GEA_EMBEDDED_DISPLAY_INTERNAL_RESERVE_BYTES asks for.
|
|
80
|
+
static void holdDisplayReserve(void *reserve);
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
} // namespace gea::framework
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
namespace gea::framework::services {
|
|
4
|
+
|
|
5
|
+
class AppState {
|
|
6
|
+
public:
|
|
7
|
+
static bool init();
|
|
8
|
+
static void lock();
|
|
9
|
+
static void unlock();
|
|
10
|
+
static const char *currentAppId();
|
|
11
|
+
static void afterAppInit();
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
} // namespace gea::framework::services
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
namespace gea::framework::services {
|
|
4
|
+
|
|
5
|
+
class BluetoothService {
|
|
6
|
+
public:
|
|
7
|
+
static void preinitForApp();
|
|
8
|
+
static void notifyConnected();
|
|
9
|
+
static void notifyDisconnected();
|
|
10
|
+
static void notifyBound();
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
} // namespace gea::framework::services
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <cstdarg>
|
|
4
|
+
#include <cstdint>
|
|
5
|
+
#include <cstddef>
|
|
6
|
+
|
|
7
|
+
namespace gea::framework::services {
|
|
8
|
+
|
|
9
|
+
class DiagnosticsFrame {
|
|
10
|
+
public:
|
|
11
|
+
virtual ~DiagnosticsFrame() = default;
|
|
12
|
+
virtual bool empty() const = 0;
|
|
13
|
+
virtual unsigned char *payload() = 0;
|
|
14
|
+
virtual int payloadCapacity() const = 0;
|
|
15
|
+
virtual bool queue(int channel, int type, const unsigned char *payload, int payload_len) = 0;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
class DiagnosticsOutput {
|
|
19
|
+
public:
|
|
20
|
+
virtual ~DiagnosticsOutput() = default;
|
|
21
|
+
virtual int write(const unsigned char *data, int len, int *err_out) = 0;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
enum class DiagnosticsSendStatus {
|
|
25
|
+
Idle,
|
|
26
|
+
Sent,
|
|
27
|
+
Backpressure,
|
|
28
|
+
Closed,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
class DiagnosticsConnection {
|
|
32
|
+
public:
|
|
33
|
+
DiagnosticsConnection();
|
|
34
|
+
~DiagnosticsConnection();
|
|
35
|
+
DiagnosticsConnection(const DiagnosticsConnection &) = delete;
|
|
36
|
+
DiagnosticsConnection &operator=(const DiagnosticsConnection &) = delete;
|
|
37
|
+
|
|
38
|
+
void reset();
|
|
39
|
+
bool hasPendingOutput() const;
|
|
40
|
+
bool wantsImmediatePoll(std::int64_t now_us) const;
|
|
41
|
+
int pollIntervalMs() const;
|
|
42
|
+
int backpressureDelayMs() const;
|
|
43
|
+
void handleIncoming(const char *data, int len);
|
|
44
|
+
DiagnosticsSendStatus flush(DiagnosticsOutput &output, std::int64_t now_us, int *err_out);
|
|
45
|
+
void prepareNextFrame(std::int64_t now_us);
|
|
46
|
+
|
|
47
|
+
private:
|
|
48
|
+
class Impl;
|
|
49
|
+
Impl *impl_;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
class DiagnosticsServer {
|
|
53
|
+
public:
|
|
54
|
+
static bool begin();
|
|
55
|
+
static int port();
|
|
56
|
+
static void start();
|
|
57
|
+
static void print(const char *fmt, ...);
|
|
58
|
+
static int vprint(const char *fmt, std::va_list args);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
class HeapProbe {
|
|
62
|
+
public:
|
|
63
|
+
static void log(const char *stage);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
class StackProbe {
|
|
67
|
+
public:
|
|
68
|
+
static void logCurrentTask(const char *stage);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
class HeapTaskSummary {
|
|
72
|
+
public:
|
|
73
|
+
static void log(const char *stage);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
} // namespace gea::framework::services
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "services/diagnostics.h"
|
|
4
|
+
|
|
5
|
+
#include <cstdarg>
|
|
6
|
+
#include <cstdint>
|
|
7
|
+
|
|
8
|
+
namespace gea::framework::services {
|
|
9
|
+
|
|
10
|
+
enum DiagnosticsWaitEvent {
|
|
11
|
+
kDiagnosticsWaitNone = 0,
|
|
12
|
+
kDiagnosticsWaitListenerReadable = 1 << 0,
|
|
13
|
+
kDiagnosticsWaitPeerReadable = 1 << 1,
|
|
14
|
+
kDiagnosticsWaitPeerWritable = 1 << 2,
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
constexpr int kDiagnosticsIoWouldBlock = -2;
|
|
18
|
+
|
|
19
|
+
class DiagnosticsPeer : public DiagnosticsOutput {
|
|
20
|
+
public:
|
|
21
|
+
~DiagnosticsPeer() override = default;
|
|
22
|
+
virtual int read(char *data, int len, int *err_out) = 0;
|
|
23
|
+
virtual void close(const char *reason, int err) = 0;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
class DiagnosticsListener {
|
|
27
|
+
public:
|
|
28
|
+
virtual ~DiagnosticsListener() = default;
|
|
29
|
+
virtual bool listen(int port) = 0;
|
|
30
|
+
virtual DiagnosticsPeer *accept() = 0;
|
|
31
|
+
virtual int wait(DiagnosticsPeer *peer, bool wait_for_peer_write, int timeout_ms, int *err_out) = 0;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
using DiagnosticsVPrintSink = int (*)(const char *, std::va_list);
|
|
35
|
+
|
|
36
|
+
class DiagnosticsPlatform {
|
|
37
|
+
public:
|
|
38
|
+
virtual ~DiagnosticsPlatform() = default;
|
|
39
|
+
virtual DiagnosticsListener &listener() = 0;
|
|
40
|
+
virtual void installLogSink(DiagnosticsVPrintSink sink) = 0;
|
|
41
|
+
virtual void startTask(void (*entry)(void *), void *context) = 0;
|
|
42
|
+
virtual std::int64_t nowUs() = 0;
|
|
43
|
+
virtual void sleepMs(int ms) = 0;
|
|
44
|
+
virtual void logInfo(const char *fmt, ...) = 0;
|
|
45
|
+
virtual void logWarn(const char *fmt, ...) = 0;
|
|
46
|
+
virtual void logError(const char *fmt, ...) = 0;
|
|
47
|
+
virtual void logHeapProbe(const char *stage) = 0;
|
|
48
|
+
virtual void logCurrentTaskStackProbe(const char *stage) { (void)stage; }
|
|
49
|
+
virtual void logHeapTaskSummary(const char *stage) { (void)stage; }
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
DiagnosticsPlatform &diagnosticsPlatform();
|
|
53
|
+
|
|
54
|
+
} // namespace gea::framework::services
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "event.h"
|
|
4
|
+
|
|
5
|
+
namespace gea::framework::services {
|
|
6
|
+
|
|
7
|
+
class EventQueue {
|
|
8
|
+
public:
|
|
9
|
+
constexpr EventQueue() = default;
|
|
10
|
+
explicit constexpr EventQueue(void *native) : native_(native) {}
|
|
11
|
+
|
|
12
|
+
explicit constexpr operator bool() const { return native_ != nullptr; }
|
|
13
|
+
constexpr void *nativeHandle() const { return native_; }
|
|
14
|
+
|
|
15
|
+
private:
|
|
16
|
+
void *native_ = nullptr;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
class FrameScheduler {
|
|
20
|
+
public:
|
|
21
|
+
using FrameCallback = void (*)(int timestamp_ms, void *context);
|
|
22
|
+
|
|
23
|
+
struct FrameCallbacks {
|
|
24
|
+
FrameCallback frame = nullptr;
|
|
25
|
+
void *context = nullptr;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
#ifndef GEA_EMBEDDED_DEFAULT_FRAME_INTERVAL_US
|
|
29
|
+
#define GEA_EMBEDDED_DEFAULT_FRAME_INTERVAL_US 16667
|
|
30
|
+
#endif
|
|
31
|
+
|
|
32
|
+
static constexpr int kDefaultFrameIntervalUs = GEA_EMBEDDED_DEFAULT_FRAME_INTERVAL_US;
|
|
33
|
+
static constexpr int kDefaultFrameIntervalMs = 16;
|
|
34
|
+
static constexpr int kMinFrameIntervalMs = 1;
|
|
35
|
+
static constexpr int kMaxFrameIntervalMs = 1000;
|
|
36
|
+
static constexpr int kFrameIntervalUs = kDefaultFrameIntervalUs;
|
|
37
|
+
static constexpr int kFrameIntervalMs = kDefaultFrameIntervalMs;
|
|
38
|
+
static constexpr int kWatchdogMs = 2000;
|
|
39
|
+
static constexpr int kEventQueueDepth = 32;
|
|
40
|
+
|
|
41
|
+
static EventQueue createEventQueue();
|
|
42
|
+
static EventQueue eventQueue();
|
|
43
|
+
static bool sendEvent(const gea::framework::events::Event &event, int wait_ms = 0);
|
|
44
|
+
static bool receiveEvent(gea::framework::events::Event *event);
|
|
45
|
+
static void start(EventQueue queue);
|
|
46
|
+
static void runFrame(const FrameCallbacks &callbacks);
|
|
47
|
+
// Graceful-overrun catch-up (see runFrame): takeCatchUpRequest() returns+clears
|
|
48
|
+
// whether the last frame overran the budget; drainFramesAndCheckInput() discards
|
|
49
|
+
// the timer's redundant queued frames and returns true if real input is waiting,
|
|
50
|
+
// so the catch-up loop yields to input but not to its own frame posts.
|
|
51
|
+
static bool takeCatchUpRequest();
|
|
52
|
+
static bool drainFramesAndCheckInput();
|
|
53
|
+
// TE-vsync single-clock pacing: when the active display has TE-sync enabled, the
|
|
54
|
+
// panel's TE edge is the ONE frame clock. The TE ISR (teEdgeIsr → notifyVsyncFromISR)
|
|
55
|
+
// becomes the sole frame producer; the scheduler's own timer stops posting frames
|
|
56
|
+
// (it stays only as a dead-TE watchdog), and the runtime loop suppresses its
|
|
57
|
+
// timer/touch frame posts + back-to-back catch-up. This eliminates the second clock
|
|
58
|
+
// (scheduler timer) that raced the TE → unstable 30-44fps pan. No effect on non-vsync
|
|
59
|
+
// apps. setVsyncDriven() is called from the display backend's setVSync().
|
|
60
|
+
static void setVsyncDriven(bool driven);
|
|
61
|
+
static bool vsyncDriven();
|
|
62
|
+
// Post exactly one (coalesced) frame from the panel TE edge ISR. ISR-safe.
|
|
63
|
+
static void notifyVsyncFromISR();
|
|
64
|
+
static void setFrameIntervalMs(int interval_ms);
|
|
65
|
+
static int frameIntervalMs();
|
|
66
|
+
static void setFrameRate(double fps);
|
|
67
|
+
static double frameRate();
|
|
68
|
+
static int nowMs();
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
} // namespace gea::framework::services
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include "services/diagnostics.h"
|
|
4
|
+
|
|
5
|
+
#include <cstdint>
|
|
6
|
+
|
|
7
|
+
namespace gea::framework::services {
|
|
8
|
+
|
|
9
|
+
class MirrorService {
|
|
10
|
+
public:
|
|
11
|
+
static int beginSnapshot();
|
|
12
|
+
static int beginDiff();
|
|
13
|
+
static int nextRecord(unsigned char *dst, int capacity);
|
|
14
|
+
static void clearDirty();
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
class MirrorTransport {
|
|
18
|
+
public:
|
|
19
|
+
~MirrorTransport();
|
|
20
|
+
|
|
21
|
+
static int pollIntervalMs();
|
|
22
|
+
|
|
23
|
+
bool enabled() const;
|
|
24
|
+
bool suppressesLogForwarding() const;
|
|
25
|
+
void reset();
|
|
26
|
+
bool handleCommand(char command);
|
|
27
|
+
bool ready(std::int64_t now) const;
|
|
28
|
+
void syncCurrentApp();
|
|
29
|
+
bool ensureBuffer(DiagnosticsFrame &pending);
|
|
30
|
+
void beginIfDue(std::int64_t now, DiagnosticsFrame &pending);
|
|
31
|
+
void appendBatch(std::int64_t now, DiagnosticsFrame &pending);
|
|
32
|
+
|
|
33
|
+
private:
|
|
34
|
+
void enable();
|
|
35
|
+
void disable();
|
|
36
|
+
void endMessage(std::int64_t now);
|
|
37
|
+
void releaseBuffer();
|
|
38
|
+
|
|
39
|
+
bool enabled_ = false;
|
|
40
|
+
bool forceSnapshot_ = true;
|
|
41
|
+
bool messageActive_ = false;
|
|
42
|
+
unsigned char *buffer_ = nullptr;
|
|
43
|
+
int cap_ = 0;
|
|
44
|
+
int heldLen_ = 0;
|
|
45
|
+
std::int64_t nextAt_ = 0;
|
|
46
|
+
char appId_[64] = "";
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
} // namespace gea::framework::services
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
namespace gea::framework::services {
|
|
4
|
+
|
|
5
|
+
struct NetworkServicesOptions {
|
|
6
|
+
// Device control and screenshots use the USB command channel. Keep the
|
|
7
|
+
// separate TCP diagnostics server opt-in so its 6 KiB task does not compete
|
|
8
|
+
// with WiFi OTA on RAM-constrained boards.
|
|
9
|
+
bool diagnosticsEnabled = false;
|
|
10
|
+
bool otaEnabled = true;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
class NetworkServices {
|
|
14
|
+
public:
|
|
15
|
+
// Records the requested service options. If early boot already connected
|
|
16
|
+
// WiFi, starts the servers immediately and returns true. Otherwise the
|
|
17
|
+
// platform WiFi bring-up calls startDeferredServers() after lazy connection.
|
|
18
|
+
static bool start(const NetworkServicesOptions &options);
|
|
19
|
+
|
|
20
|
+
// Starts diagnostics/OTA per the options recorded by start(). Called by the
|
|
21
|
+
// platform WiFi driver once the radio is up and connected.
|
|
22
|
+
static void startDeferredServers();
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
} // namespace gea::framework::services
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <cstddef>
|
|
4
|
+
#include <cstdint>
|
|
5
|
+
|
|
6
|
+
namespace gea::framework::services {
|
|
7
|
+
|
|
8
|
+
class OtaServer {
|
|
9
|
+
public:
|
|
10
|
+
enum class Result : std::uint8_t {
|
|
11
|
+
Ok = 0,
|
|
12
|
+
InvalidSize = 1,
|
|
13
|
+
NoPartition = 2,
|
|
14
|
+
BeginFailed = 3,
|
|
15
|
+
WriteFailed = 4,
|
|
16
|
+
SizeMismatch = 5,
|
|
17
|
+
ValidationFailed = 6,
|
|
18
|
+
BootSelectionFailed = 7,
|
|
19
|
+
NotStarted = 8,
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
static bool start();
|
|
23
|
+
static Result beginImage(std::size_t imageSize);
|
|
24
|
+
static Result writeImage(const std::uint8_t *data, std::size_t length);
|
|
25
|
+
static Result finishImage();
|
|
26
|
+
static void abortImage();
|
|
27
|
+
static std::size_t receivedBytes();
|
|
28
|
+
static std::size_t expectedBytes();
|
|
29
|
+
static void rebootSoon();
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
} // namespace gea::framework::services
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
#include <string>
|
|
4
|
+
|
|
5
|
+
namespace gea::framework::services {
|
|
6
|
+
|
|
7
|
+
class StorageService {
|
|
8
|
+
public:
|
|
9
|
+
static bool init();
|
|
10
|
+
|
|
11
|
+
// Persistent key/value strings (NVS "gea" namespace on esp32). getString
|
|
12
|
+
// fills buf and returns true iff the key exists; setString persists + commits.
|
|
13
|
+
// Used for device settings such as the default launch app (read at boot).
|
|
14
|
+
static bool getString(const char *key, char *buf, unsigned capacity);
|
|
15
|
+
static bool setString(const char *key, const char *value);
|
|
16
|
+
|
|
17
|
+
// Whole-store blob persistence for the app-facing `localStorage` (see
|
|
18
|
+
// gea::host::StorageFacade). The facade keeps the live key/value set in RAM
|
|
19
|
+
// and serializes it to one opaque, binary-safe blob; loadKv restores it at
|
|
20
|
+
// boot (empty `out` if none stored), saveKv persists it (an empty blob clears
|
|
21
|
+
// the slot). Backed by an NVS blob on esp32, RAM elsewhere.
|
|
22
|
+
static bool loadKv(std::string &out);
|
|
23
|
+
static void saveKv(const std::string &blob);
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
} // namespace gea::framework::services
|
package/include/touch.h
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#pragma once
|
|
2
|
+
|
|
3
|
+
namespace gea::platform::touch {
|
|
4
|
+
|
|
5
|
+
enum class Phase {
|
|
6
|
+
Down = 1,
|
|
7
|
+
Move = 2,
|
|
8
|
+
Up = 3,
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
class Touchscreen {
|
|
12
|
+
public:
|
|
13
|
+
using Observer = void (*)(Phase phase, bool touching, int x, int y);
|
|
14
|
+
// Multi-finger variant: same event plus a 0-based finger index (0 = primary).
|
|
15
|
+
// Controllers that support simultaneous touches (e.g. the GT911) report every
|
|
16
|
+
// finger through this. Single-touch controllers leave it unimplemented; the
|
|
17
|
+
// weak default in touch_runtime.cpp is a no-op, so those targets keep using
|
|
18
|
+
// the single Observer with no code change.
|
|
19
|
+
using PointerObserver = void (*)(Phase phase, bool touching, int x, int y, int pointerId);
|
|
20
|
+
|
|
21
|
+
static void setObserver(Observer observer);
|
|
22
|
+
// Optional: register a multi-finger observer. Default (weak) no-op.
|
|
23
|
+
static void setPointerObserver(PointerObserver observer);
|
|
24
|
+
static bool init();
|
|
25
|
+
// Optional event-loop polling hook. Controllers backed by interrupts or their
|
|
26
|
+
// own driver task use the weak no-op implementation.
|
|
27
|
+
static void poll(int nowMs);
|
|
28
|
+
static int read(int *x, int *y);
|
|
29
|
+
static int readCached(int *x, int *y);
|
|
30
|
+
static void consumeLatestMove(int *x, int *y);
|
|
31
|
+
// Inject a synthetic touch event through the same path as the hardware
|
|
32
|
+
// reader: updates the latest-move cache (so consumeLatestMove returns these
|
|
33
|
+
// coords) and notifies the observer. Used by the debug FIFO so injected
|
|
34
|
+
// drags behave exactly like a real finger.
|
|
35
|
+
static void injectEvent(Phase phase, bool touching, int x, int y);
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
} // namespace gea::platform::touch
|