src.nth.io/

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.clangd2
-rw-r--r--.gitignore6
-rw-r--r--CMakeLists.txt8
-rw-r--r--README.md100
-rw-r--r--main/CMakeLists.txt2
-rw-r--r--main/app_main.cpp22
-rw-r--r--partitions.csv6
-rw-r--r--sdkconfig.defaults31
8 files changed, 177 insertions, 0 deletions
diff --git a/.clangd b/.clangd
new file mode 100644
index 0000000..e95990a
--- /dev/null
+++ b/.clangd
@@ -0,0 +1,2 @@
+CompileFlags:
+ CompilationDatabase: build/
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..e597f25
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+build/
+sdkconfig
+sdkconfig.old
+dependencies.lock
+managed_components/
+/.cache/
diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..5281b89
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,8 @@
+cmake_minimum_required(VERSION 3.16)
+
+set(PROJECT_VER "0.1")
+set(PROJECT_VER_NUMBER 1)
+
+include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+
+project(scrypted-viewport)
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..22b102e
--- /dev/null
+++ b/README.md
@@ -0,0 +1,100 @@
+# Scrypted Viewport v1 Technical Design Specification
+
+Version: 1.0
+
+## Overview
+
+Scrypted Viewport is an Ethernet-powered ambient display appliance optimized for Scrypted camera and doorbell events.
+
+Design goals:
+- No Matter
+- No HomeKit
+- No polling
+- No configuration UI
+- No authentication
+- No rendering engine
+- No business logic on the device
+
+Scrypted owns rendering, overlays, camera selection and interaction logic.
+
+Scrypted Viewport owns Ethernet, JPEG decode, display, touch input and callback delivery.
+
+## Hardware
+
+### Controller
+Waveshare ESP32-P4-ETH-POE
+
+### Display
+5" 800x480 IPS Capacitive Touch MIPI DSI display
+
+## Boot
+
+Power
+-> DHCP
+-> mDNS (_scrypted-viewport._tcp.local)
+-> Wait
+
+## Resolution
+
+800x480 native.
+
+Scrypted always renders 800x480 JPEGs.
+
+## API
+
+GET /health
+
+POST /config
+{
+ "display":"mudroom",
+ "callback":"http://scrypted.local:11080/api/viewport/touch"
+}
+
+POST /frame
+Content-Type: image/jpeg
+
+POST /sleep
+
+POST /brightness
+{
+ "brightness":75
+}
+
+## Touch Callback
+
+{
+ "display":"mudroom",
+ "event":"tap",
+ "timestamp":1730000000
+}
+
+Supported:
+- tap
+- long_press
+- swipe_left
+- swipe_right
+
+## Build
+
+```sh
+source ~/Dev/code/git/esp32/env.sh
+cd ~/Dev/code/git/esp32/projects/esp32-poe-scrypted-viewport
+idf.py set-target esp32p4
+idf.py build
+idf.py -p /dev/cu.usbmodem* flash monitor
+```
+
+## Philosophy
+
+Scrypted Viewport is a thin network framebuffer appliance.
+
+ESP:
+- DHCP
+- mDNS
+- HTTP server
+- JPEG decode
+- framebuffer
+- touch
+- callback
+
+Everything else belongs in Scrypted.
diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt
new file mode 100644
index 0000000..e088a07
--- /dev/null
+++ b/main/CMakeLists.txt
@@ -0,0 +1,2 @@
+idf_component_register(SRC_DIRS "."
+ INCLUDE_DIRS ".")
diff --git a/main/app_main.cpp b/main/app_main.cpp
new file mode 100644
index 0000000..55dbd5d
--- /dev/null
+++ b/main/app_main.cpp
@@ -0,0 +1,22 @@
+#include <esp_log.h>
+#include <esp_event.h>
+#include <esp_netif.h>
+#include <nvs_flash.h>
+
+static const char *TAG = "viewport";
+
+extern "C" void app_main(void)
+{
+ ESP_ERROR_CHECK(nvs_flash_init());
+ ESP_ERROR_CHECK(esp_netif_init());
+ ESP_ERROR_CHECK(esp_event_loop_create_default());
+
+ ESP_LOGI(TAG, "Scrypted Viewport boot");
+
+ // TODO: Ethernet (ESP32-P4 EMAC + Waveshare PoE PHY)
+ // TODO: mDNS _scrypted-viewport._tcp.local
+ // TODO: HTTP server: /health /config /frame /sleep /brightness
+ // TODO: MIPI-DSI panel init (800x480 IPS)
+ // TODO: JPEG decode -> framebuffer
+ // TODO: Capacitive touch -> callback POST
+}
diff --git a/partitions.csv b/partitions.csv
new file mode 100644
index 0000000..19a82fa
--- /dev/null
+++ b/partitions.csv
@@ -0,0 +1,6 @@
+# Name, Type, SubType, Offset, Size, Flags
+nvs, data, nvs, 0x9000, 0x6000,
+phy_init, data, phy, , 0x1000,
+otadata, data, ota, , 0x2000,
+ota_0, app, ota_0, 0x20000, 0x300000,
+ota_1, app, ota_1, , 0x300000,
diff --git a/sdkconfig.defaults b/sdkconfig.defaults
new file mode 100644
index 0000000..3f88f72
--- /dev/null
+++ b/sdkconfig.defaults
@@ -0,0 +1,31 @@
+CONFIG_IDF_TARGET="esp32p4"
+
+# Partition table
+CONFIG_PARTITION_TABLE_CUSTOM=y
+CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv"
+
+# PSRAM (required for 800x480 framebuffer + JPEG decode)
+CONFIG_SPIRAM=y
+CONFIG_SPIRAM_MODE_HEX=y
+CONFIG_SPIRAM_SPEED_200M=y
+CONFIG_SPIRAM_USE_MALLOC=y
+CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=16384
+
+# Ethernet (Waveshare ESP32-P4-ETH-POE: internal EMAC + external PHY)
+CONFIG_ETH_ENABLED=y
+CONFIG_ETH_USE_ESP32_EMAC=y
+
+# LWIP / mDNS
+CONFIG_LWIP_IPV4=y
+CONFIG_LWIP_IPV6=y
+CONFIG_MDNS_MAX_INTERFACES=1
+
+# HTTP server
+CONFIG_HTTPD_MAX_REQ_HDR_LEN=1024
+CONFIG_HTTPD_MAX_URI_LEN=512
+
+# Main task stack — JPEG decode is hungry
+CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192
+
+# Log level
+CONFIG_LOG_DEFAULT_LEVEL_INFO=y