FrameFilm(帧影)is a family of color e-paper products and the tools that go with them.
The hardware includes fridge magnets (Standard / Pro), the Max desktop photo album, the Ark passport edition and the Dock e-paper base. Every product uses a color e-paper panel that keeps its image without power, and accepts images from a phone, the web or a cloud service over Bluetooth, WiFi or USB.
“帧影” means “one frame, one shadow — freezing time”. The English name FrameFilm combines “frame” and “film”.
Companion software includes the on-device apps (photos / templates / clock / animation / passport), the ForFilm web tool, a WeChat mini program, a Flutter mobile app, and the self-hosted Film-hub cloud service.
| Product | Firmware directory | Display | Highlights |
|---|---|---|---|
| Fridge magnet Standard | firmware/frame_film(FRAMEFILM_STD) |
3.6” 600×400 | Rotary encoder with button, WS2812 LED |
| Fridge magnet Pro | firmware/frame_film(FRAMEFILM_PRO) |
3.68” 792×528 | Three buttons, WiFi, wireless charging |
| Photo album Max | firmware/frame_film(FRAMEFILM_MAX) |
7.09” 1200×1600 dual panel | Large photo album, three buttons, no LED |
| Passport edition Ark | firmware/frame_film_ark |
3.70” 720×480 | Single model; app framework and LVGL UI layer |
| E-paper Dock | firmware/frame_film_dock |
3.64” 760×568 | USB composite device: audio + HID keyboard + CDC serial |
| Xiaoying FilmReader | Derivative build (FrameFilm mainboard + CrossMux firmware) | 3.97” 800×480 four-gray | Monochrome e-paper reader; four buttons, SD card, wireless charging |
Standard / Pro / Max share one firmware, separated at compile time by model macros and
sdkconfig; the panel can be chosen per model inhal_epd.h(see “Selectable Screens” below).
Schematics, PCBs, BOMs, enclosures and production files are published on OSHWHub:
| Project | Description |
|---|---|
| FrameFilm Standard | Fridge magnet base model, E6 full-color V2 |
| FrameFilm Spark Edition | Optimized circuit: NU1680 wireless charging, 32-pin 3.7” and 24-pin 1.54” E6 support, three hardware variants |
| FrameFilm Dock | E-paper base (audio / HID / CDC) |
| Xiaoying FilmReader | 3.97” monochrome e-paper reader derivative build |
Derivative modules:
| Module | Description |
|---|---|
| E-Ink color E6 driver module | For 3.6 / 4 / 7.3 inch Waveshare and Good Display E6 color panels |
| NU1680 wireless charging receiver | 5V / 1A, Qi compatible, 15×10×0.8 mm, optional reverse-current protection, MIT licensed |
Mainboard design and firmware are maintained in this repository; OSHWHub projects are for fabrication and reproduction — BOM, assembly and fabrication parameters follow each project’s attachments.
0x4E) and time sync (0x4D).All three firmware lines follow a one-way film_service → film_hal → film_sys layering; reverse dependencies are not allowed.
| Component | Responsibility | frame_film |
frame_film_ark |
frame_film_dock |
|---|---|---|---|---|
film_sys |
System init, logging, config, event bus | ✅ | ✅ | ✅ |
film_service |
BLE, file management, photo playback, parameter storage | ✅ | ✅ | ✅ |
film_hal |
E-paper, battery, LED, input, SD, USB | ✅ | ✅ | ✅ |
film_app |
App framework: scheduling, menu, settings, content apps | — | ✅ | — |
film_ui |
LVGL UI layer: page lifecycle, display pipeline, assets | — | ✅ | — |
The Dock shares one command parser (
film_service/src/service_cmd.c) between BLE and USB — new commands only need to be added there.
Panels are not tied to a model: inside the model branch of hal_epd.h, set the target EPD_SELECT_E6_* to 1 and the others to 0.
| Panel | Resolution | Panel ID | Macro | Driver |
|---|---|---|---|---|
| 3.68” | 792×528 | 0x01 | EPD_SELECT_E6_3_68_792_528 |
hal_epd_368.c |
| 3.70” | 720×480 | 0x02 | EPD_SELECT_E6_3_70_720_480 |
hal_epd_370.c |
| 3.6” | 600×400 | 0x03 | EPD_SELECT_E6_3_60_600_400 |
hal_epd_360.c |
| 1.54” | 240×240 | 0x04 | EPD_SELECT_E6_1_54_240_240 |
— |
| 7.09” dual panel | 1200×1600 | 0x05 | EPD_SELECT_E6_7_09_1600_1200 |
hal_epd_709.c |
| 3.64” | 760×568 | 0x06 | EPD_SELECT_E6_3_64_760_568 |
hal_epd_364.c(Dock default) |
| 3.98” | 768×552 | 0x07 | EPD_SELECT_E6_3_98_768_552 |
hal_epd_398.c |
| 3.98” four-color | 768×552 | 0x08 | EPD_SELECT_E4_3_98_768_552 |
hal_epd_398e4.c |
| 3.97” monochrome | 800×480 | — | — | FilmReader uses SSD1677 (four-gray); no driver in this repo |
0x07(SE0398 3.98”) is a newly added option, disabled by default; set it to1to enable. It uses 4-wire SPI + DC and only fits the STD / Pro wiring (the Max has no DC pin).0x08(JD79665AA 3.98” four-color) only has black/white/yellow/red; ForFilm detects this panel and outputs four-color images automatically. A full refresh takes about 15 s, and it also only fits STD / Pro wiring. The 3.97” monochrome panel (SSD1677) is used by the Xiaoying FilmReader derivative build, which runs CrossMux firmware; none of the three firmware lines here include its driver. See “Xiaoying FilmReader” below. The panel ID is returned to clients in the0x42response so they can correct the resolution; the client still identifies the model by the BLE advertising name.
| Parameter | Spec |
|---|---|
| MCU | ESP32-S3 WROOM N16R8 |
| Display | Color e-paper 3.6” 600×400 (WFT driver) |
| Storage | TF card up to 32GB or built-in SD NAND |
| Connectivity | Bluetooth BLE 4.2 |
| Input | Rotary encoder with button |
| Battery | Li-ion 304040, 1.5 mm connector |
| Dimensions | Approx. 92 × 60 × 7 mm |
| Mounting | Rear magnets 2x12mm-1mm, 1x15mm-2mm |
| Parameter | Spec |
|---|---|
| MCU | ESP32-S3 mini N4R2 |
| Display | Color e-paper 3.68” 792×528 (SE0368-C driver) |
| Storage | Built-in SD NAND |
| Connectivity | Bluetooth BLE 4.2 / WiFi |
| Input | Three buttons |
| Battery | Li-ion 244147 |
| Charging | Wireless charging (MagSafe compatible) |
| Dimensions | Approx. 90 × 59 × 5 mm |
| Mounting | Rear MagSafe magnet ring |
| Parameter | Spec |
|---|---|
| MCU | ESP32-S3 N16R8 (16MB Flash / Octal PSRAM) |
| Display | Color e-paper 7.09” 1200×1600 dual panel |
| Storage | TF card |
| Connectivity | Bluetooth BLE 4.2 |
| Input | Three buttons |
| LED | No RGB LED |
| Battery | No battery level detection |
| Parameter | Spec |
|---|---|
| MCU | ESP32-S3 N4R2 (4MB Flash / Quad PSRAM) |
| Display | Color e-paper 3.70” 720×480 (panel ID 0x02) |
| Storage | TF card with detect pin |
| Connectivity | Bluetooth BLE 4.2 |
| Input | Three buttons (up / down / confirm, active low) |
| LED | WS2812 (white = disconnected, green = connected, red = low battery) |
| Battery | Li-ion with level detection |
| Parameter | Spec |
|---|---|
| MCU | ESP32-S3 N16R8 (16MB Flash / Octal PSRAM) |
| Display | Color e-paper 3.64” 760×568 (panel ID 0x06) |
| USB | Composite: UAC audio + HID keyboard + CDC virtual serial (VID/PID 0x303A/0x8000) |
| Audio | ES8311 + NS4150B voice module (microphone + speaker) |
| Input | Three buttons (sent as PC keyboard key codes) |
| Connectivity | Bluetooth BLE 4.2 + USB |
Xiaoying FilmReader is a 3.97 inch monochrome e-paper reader built on the FrameFilm mainboard. It is a derivative build: the core circuit follows the FrameFilm mainboard, with adaptations mainly in the PCB panel, enclosure, front panel and final assembly. It has no touch and no backlight, only four buttons; its value lies in low-cost reproduction, firmware hacking and enclosure remixing.
OSHWHub project (schematic / PCB / BOM / enclosure / front panel): https://oshwhub.com/kiritro/project_bppplpbn
| Parameter | Spec |
|---|---|
| MCU | ESP32-S3 (16MB Flash / 8MB PSRAM) |
| Display | Monochrome four-gray 3.97” 800×480 (SSD1677) |
| Storage | SD card (4-bit SDMMC) |
| Input | Four buttons: UP / DOWN / CONFIRM+PWR / BACK |
| Charging | MagSafe wireless charging |
| Other | 32.768 kHz RTC crystal, WS2812 status LED, peripheral power cut in deep sleep |
| Mainboard config | Reuses the FrameFilm mainboard; solder pads P1 open / P2 open / P3 bridged |
firmware.factory.bin from the OSHWHub attachmentsFilmReader外壳.3mf and BOM_Board_FilmReader材料清单.xlsx are attached to the OSHWHub project; the front panel is ordered as 0.8 mm acrylic, adhesive-backed, standard light-blocking, reverse printingThe mainboard design is shared with FrameFilm and follows this repository’s GPLv3 license; the reader firmware and build files are maintained in the CrossMux repository and the OSHWHub project respectively.
FrameFilm/
├── assets/ # Assets
│ └── pic/ # Product photos and renders
│
├── docs/ # Documentation
│ ├── blecmd/ # BLE protocol docs
│ ├── datasheet/ # Chip and module datasheets
│ ├── film/ # Film file format spec
│ ├── filmhub/ # Cloud frame service design
│ ├── filmagent/ # Voice interaction (FilmAgent) design and audio drivers
│ ├── hardware/ # Hardware specification docs
│ ├── knowledge/ # AI knowledge base (architecture / conventions / command reference)
│ ├── wifi/ # WiFi feature notes
│ ├── ci-builds.md # Ark CI builds and releases
│ └── ARK_CHANGELOG.md # Passport edition changelog
│
├── firmware/ # Device firmware (ESP-IDF)
│ ├── frame_film/ # Fridge magnet / photo album (three models, selectable panel)
│ │ ├── components/
│ │ │ ├── film_service/ # Service layer
│ │ │ ├── film_sys/ # System layer
│ │ │ └── film_hal/ # Hardware abstraction layer
│ │ ├── main/ # Entry point
│ │ └── sdkconfig_* # Per-model configs (std/pro/max)
│ ├── frame_film_ark/ # Passport edition (single model; app framework + UI layer)
│ └── frame_film_dock/ # E-paper base (single model; BLE + USB)
│
├── app/ # Mobile apps
│ ├── android/ # Ark Android client (Kotlin communication core)
│ └── flutter_app/ # Ark Flutter client (current main UI)
│
├── hardware/ # Hardware design
│ ├── pcb/ # PCB schematics
│ └── model/ # Enclosure 3D models
│
├── server/ # Cloud services
│ └── filmhub/ # film-hub (LAN backend + admin frontend)
│ ├── backend/ # Backend API (FastAPI)
│ └── web/ # Web admin frontend
│
├── tools/ # Developer tools
│ ├── ForFilm/ # Web frame manager (BLE / USB / serial)
│ ├── wechart/ # WeChat mini program
│ ├── framefilm-dock-upload/ # Dock USB image upload tool
│ ├── convert/ # Photo conversion tool
│ ├── ui-mockup/ # On-device UI mockups
│ ├── ui-assets/ # UI icon / boot image generation
│ ├── ui-fonts/ # UI font generation
│ ├── clock-font/ # Large clock digit font generation
│ ├── ark-font/ # Passport font generation
│ ├── ark-pass-editor/ # Passport profile editor
│ ├── ark-ui-simulator/ # Ark UI simulator
│ └── film_viewer/ # film file viewer
│
├── AGENTS.md # AI development guide
├── README.md # Chinese README
├── README.en.md # English README
└── LICENSE # License
There are three firmware projects. Only frame_film requires model configuration (swap sdkconfig + set the model macro + pick a panel). frame_film_ark (passport edition, single model, with 4MB/Quad and 16MB/Octal storage variants) builds out of the box — see below for switching variants. frame_film_dock (base, single model) builds and flashes directly.
The app framework and UI layer (LVGL + app layer) exist only in
frame_film_ark;frame_filmis the classic firmware without app or UI layers.
The following steps configure frame_film (three models):
sdkconfig: copy firmware/frame_film/sdkconfig_<model> to sdkconfigfirmware/frame_film/components/film_sys/inc/sys_cfg.h and enable exactly one model macrofirmware/frame_film/components/film_hal/inc/hal_epd.h, set the target EPD_SELECT_E6_* to 1 and the others to 0 inside the corresponding model branch| Model | sdkconfig to use | sys_cfg.h macro |
Default panel |
|---|---|---|---|
| Standard | sdkconfig_std |
FRAMEFILM_STD |
3.6” 600×400 |
| Pro | sdkconfig_pro |
FRAMEFILM_PRO |
3.68” 792×528 |
| Max (photo album) | sdkconfig_max |
FRAMEFILM_MAX |
7.09” 1200×1600 dual panel |
See the “Selectable Screens” table above for optional panels and their macros.
cd firmware/frame_film
cp sdkconfig_std sdkconfig # Example: Standard; same for Pro/Max
idf.py build
idf.py flash monitor
ForFilm’s “Settings → Serial flash · full firmware” writes to flash directly through the browser’s Web Serial API, equivalent to idf.py flash. It is faster than BLE OTA and can also write the bootloader and partition table (OTA only writes the app partition).
tools as the root).bootloader.bin, partition-table.bin, ota_data_initial.bin and frame_film.bin from build/ at once; offsets are matched automatically by filename (0x0 / 0x8000 / 0x29000 / 0x30000).idf.py merge-bin; the page detects it and writes from 0x0.Close programs that hold the serial port (such as
idf.py monitor) before flashing. When selecting only the app image, do not enable “merged image”, otherwise it is written from 0x0 and overwrites the bootloader.build/artifacts fromframe_film_arkandframe_film_dockcan also be flashed through this page.
Passport edition / Dock:
cd firmware/frame_film_ark # Passport edition FRAMEFILMARK (3.70" 720×480, three buttons)
idf.py build flash monitor # Default n4r2: 4MB Flash / Quad PSRAM
.\build.ps1 n16r8 flash COM15 # n16r8: 16MB Flash / Octal PSRAM (PowerShell)
cd firmware/frame_film_dock # E-paper base FRAMEFILMDOCK (3.64" 760×568)
idf.py build flash monitor
frame_film_arkships two configs —sdkconfig(n4r2) andsdkconfig_n16r8— switched withbuild.ps1or VS Code’sESP-IDF: Select project configuration;frame_film_dockhas a singlesdkconfig. Neither requires model / panel macros.
The repository includes .vscode/settings.json (IDF path already configured):
firmware/frame_film (or firmware/frame_film_ark for the passport edition, firmware/frame_film_dock for the Dock)sdkconfig + set the model macro in sys_cfg.h) — only frame_film needs this; skip it for frame_film_ark / frame_film_dockESP-IDF: Select project configuration → n4r2 (4MB/Quad, default) or n16r8 (16MB/Octal); build directories are build_n4r2 / build_n16r8Ctrl+E then BCtrl+E then FCtrl+E then M (Ctrl+] to exit)The first build takes a while — that is normal. If you change the port or chip, just reselect it in the status bar.
The current Ark mobile client is the Flutter project (app/flutter_app/), reusing the Kotlin BLE / WiFi Direct core in app/android/ without a WebView:
Build, verification scope and signing are documented in app/flutter_app/README.md and docs/ci-builds.md.
The Dock enumerates as a virtual serial port when plugged into a PC, so the bundled script can upload images directly:
# Upload one image (auto port detection → handshake → convert → upload → read-back verify)
python tools/framefilm-dock-upload/scripts/dock_upload.py photo.jpg
# List / verify film files already on the device
python tools/framefilm-dock-upload/scripts/dock_upload.py --list
See tools/framefilm-dock-upload/SKILL.md for all options and troubleshooting.
The ForFilm web tool supports:
Online tool (GitHub Pages): 👉 FrameFilm Web Tool
The FrameFilm WeChat mini program makes it easy to manage and transfer photos from a phone:
Scan the mini program code to try it.

A self-hosted LAN frame service providing WiFi content push, template rendering and remote management:
Stack: FastAPI + SQLite + Vue 3, single-machine LAN deployment.
server/filmhub/backend/ | Web frontend: server/filmhub/web/A voice interaction direction for the Dock: spoken conversation drives e-paper content generation, reusing the Film-hub backend. Currently in the design and audio-driver stage — see docs/filmagent/.
See each module’s README for details:
Technical documentation:
FrameFilm is an open-source learning and hobby project. All source code, hardware designs, documentation and materials are provided “as is” for learning, research and non-commercial reference.
Using this project means you have read and agree to the above terms.
This project is licensed under the GNU General Public License v3.0 (GPLv3).