summaryrefslogtreecommitdiff
path: root/src/driver_emulator.cpp
diff options
context:
space:
mode:
authorkkard2 <[email protected]>2026-06-10 14:06:55 +0200
committerkkard2 <[email protected]>2026-06-10 14:06:55 +0200
commitf961306d40654ac6a1ab7c262af7af74401dc693 (patch)
tree6e2b0366f0ec077eadb815b35718312d1c79ea33 /src/driver_emulator.cpp
init
Diffstat (limited to 'src/driver_emulator.cpp')
-rw-r--r--src/driver_emulator.cpp169
1 files changed, 169 insertions, 0 deletions
diff --git a/src/driver_emulator.cpp b/src/driver_emulator.cpp
new file mode 100644
index 0000000..d808fcd
--- /dev/null
+++ b/src/driver_emulator.cpp
@@ -0,0 +1,169 @@
+#include <raylib.h>
+#include <stdlib.h>
+
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#define WIFI_HOTSPOT_IP "127.0.0.1"
+
+static uint16_t display_framebuffer[DISPLAY_WIDTH * DISPLAY_HEIGHT];
+static bool display_state;
+
+void display_setup(void) {
+ InitWindow(DISPLAY_WIDTH, DISPLAY_HEIGHT, "ILI9341 screen");
+}
+
+void display_on(void) {
+ display_state = true;
+}
+
+void display_off(void) {
+ display_state = false;
+}
+
+void display_begin(void) {}
+
+void display_end(void) {
+ BeginDrawing();
+ if (display_state) {
+ for (int32_t y = 0; y < DISPLAY_HEIGHT; y++) {
+ for (int32_t x = 0; x < DISPLAY_WIDTH; x++) {
+ uint16_t c = display_framebuffer[y * DISPLAY_WIDTH + x];
+ uint8_t r = (c & 0b1111100000000000) >> 8;
+ uint8_t g = (c & 0b0000011111100000) >> 3;
+ uint8_t b = (c & 0b0000000000011111) << 3;
+ DrawPixel(x, y, (Color){ r, g, b, 255 });
+ }
+ }
+ } else {
+ for (int32_t y = 0; y < DISPLAY_HEIGHT; y++) {
+ for (int32_t x = 0; x < DISPLAY_WIDTH; x++) {
+ DrawPixel(x, y, (Color){ 0, 0, 0, 255 });
+ }
+ }
+ }
+ EndDrawing();
+
+ if (WindowShouldClose()) {
+ CloseWindow();
+ exit(1);
+ }
+}
+
+void display_clear(uint16_t color) {
+ for (int i = 0; i < DISPLAY_WIDTH * DISPLAY_HEIGHT; i++)
+ display_framebuffer[i] = color;
+}
+
+void display_set_pixel(int32_t x, int32_t y, uint16_t color) {
+ if (x < 0 || x >= DISPLAY_WIDTH || y < 0 || y >= DISPLAY_HEIGHT)
+ return;
+ display_framebuffer[y * DISPLAY_WIDTH + x] = color;
+}
+
+
+void button_setup(void) { }
+bool button_get(void) {
+ PollInputEvents();
+ return IsKeyDown(KEY_SPACE);
+}
+
+
+static int server_fd = -1;
+static WifiHandler current_handler = nullptr;
+
+static void set_nonblocking(int fd) {
+ fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
+}
+
+void wifi_setup(void) { }
+
+void wifi_hotspot_start(const char *ssid, const char *password, WifiHandler handler) {
+ (void)ssid; (void)password;
+ current_handler = handler;
+
+ server_fd = socket(AF_INET, SOCK_STREAM, 0);
+ if (server_fd < 0) { printf("socket failed: %s\n", strerror(errno)); return; }
+
+ int opt = 1;
+ if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
+ printf("setsockopt failed: %s\n", strerror(errno));
+
+ set_nonblocking(server_fd);
+
+ struct sockaddr_in addr = {};
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(8080);
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ if (bind(server_fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
+ { printf("bind failed: %s\n", strerror(errno)); return; }
+
+ if (listen(server_fd, 4) < 0)
+ { printf("listen failed: %s\n", strerror(errno)); return; }
+
+ printf("emulated hotspot at http://localhost:8080\n");
+}
+
+void wifi_hotspot_stop(void) {
+ if (server_fd >= 0) {
+ close(server_fd);
+ server_fd = -1;
+ printf("stopped hotspot\n");
+ }
+}
+
+void wifi_tick(void) {
+ if (server_fd < 0) return;
+
+ int client = accept(server_fd, nullptr, nullptr);
+ if (client < 0) { // no pending connection, non-blocking
+ if (errno != EAGAIN && errno != EWOULDBLOCK)
+ printf("accept error: %s\n", strerror(errno));
+ return;
+ }
+ printf("got connection\n");
+
+ char buf[2048] = {};
+ read(client, buf, sizeof(buf) - 1);
+
+ // parse first line: "GET /uri HTTP/1.1"
+ char method[8] = {}, uri[256] = {};
+ sscanf(buf, "%7s %255s", method, uri);
+
+ // find body after \r\n\r\n
+ const char *body = strstr(buf, "\r\n\r\n");
+ if (body) body += 4;
+
+ WifiRequest req = {
+ .uri = uri,
+ .method = method,
+ .body = (body && *body) ? body : nullptr,
+ };
+
+ WifiResponse res = current_handler(&req);
+
+ char header[256];
+ snprintf(header, sizeof(header),
+ "HTTP/1.1 %d OK\r\n"
+ "Content-Type: %s\r\n"
+ "Content-Length: %zu\r\n"
+ "Connection: close\r\n"
+ "\r\n",
+ res.status, res.content_type, strlen(res.body)
+ );
+
+ write(client, header, strlen(header));
+ write(client, res.body, strlen(res.body));
+ close(client);
+}
+
+
+uint32_t millis() {
+ return (uint32_t)(GetTime() * 1000);
+}