Skip to main content

mowatch-dev

Development guide for MoWatch e-ink smartwatch apps. Use when developing watch faces, apps, or processing images for MoWatch. Includes complete API reference, bitmap format, Docker build process, and image processing for 1-bit e-ink display.

Zur Installation springen

Quellinformationen

Repository
yetone/agent-skill-mowatch-dev
Letzte Quellaktivität
3. Februar 2026 um 08:22
Erkannte Sprache von SKILL.md
Englisch
Sterne
7
Forks
0

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
mowatch-dev
description
Development guide for MoWatch e-ink smartwatch apps. Use when developing watch faces, apps, or processing images for MoWatch. Includes complete API reference, bitmap format, Docker build process, and image processing for 1-bit e-ink display.
license
MIT
# MoWatch App Development Skill Use this skill when developing watch faces or apps for MoWatch e-ink smartwatch. ## SDK Files Location **IMPORTANT**: SDK source files are located in this skill's directory. Copy them to create a new project: ``` ~/.claude/skills/mowatch-dev/ ├── sdk/ │ ├── include/header.h # SDK header - copy to include/ │ └── libs/ │ ├── init_datas.c # API wrappers - copy to libs/ │ └── syscall_gcc.txt # Syscall addresses - copy to libs/ └── templates/ ├── Makefile # Build config - copy to gcc/ ├── app.ld # Linker script - copy to gcc/ └── createmwa.py # Package creator - copy to gcc/ ``` To create a new project, read and copy these files using the Read tool. ## Hardware Specifications - **Display**: 200x200 pixel monochrome e-ink - **MCU**: ARM Cortex-M3 - **Colors**: Black and white only (1-bit) - **Update**: Partial refresh supported, full refresh every 5 minutes recommended ## Memory Constraints (IMPORTANT!) ```c FLASH (rx) : ORIGIN = 0x10050000, LENGTH = 40K // Code + constants RAM (xrw) : ORIGIN = 0x11001000, LENGTH = 4K // Variables only! ``` **Only 4K RAM available!** Keep global variables minimal. Use `const` for bitmap data. ## Constants ```c #define SCREEN_WIDTH 200 #define SCREEN_HEIGHT 200 #define BLACK 0 #define WHITE 0xFF #define GREY 0x80 #define MODE_EMPTY 0 // Rectangle outline #define MODE_FILL 1 // Filled rectangle // File access flags #define FA_READ 0x01 #define FA_WRITE 0x02 #define FA_OPEN_EXISTING 0x00 #define FA_CREATE_NEW 0x04 #define FA_CREATE_ALWAYS 0x08 #define FA_OPEN_ALWAYS 0x10 #define FA_OPEN_APPEND 0x30 ``` ## Enums and Data Structures ### Update Types ```c typedef enum UPDAT_TYPE { FULL_UPDATE, // Full screen refresh (prevents ghosting) PART_UPDATE, // Partial refresh (faster but may ghost) NONE_UPDATE, // No screen update } UpdateType; ``` ### Button Types ```c typedef enum MBUTTON_TYPE { KEY_NULL, KEY_CENTER, // Center button press KEY_UP, // Up button press KEY_DOWN, // Down button press KEY_CENTER_UP, // Center then Up KEY_UP_CENTER, // Up then Center KEY_CENTER_DOWN, // Center then Down KEY_DOWN_CENTER, // Down then Center KEY_UP_DOWN, // Up then Down KEY_DOWN_UP, // Down then Up KEY_BACK, // Back/exit } ButtonType; ``` ### Rotation ```c typedef enum ROTATE { ROTATE_0, ROTATE_90, ROTATE_180, ROTATE_270, } Rotate; ``` ### Bluetooth State ```c typedef enum BLUESTTE { DISCONNECTED, CONNECTING, CONNECTED, } BlueState; ``` ### Weather Data ```c typedef enum WEATHERDAY { TOTDAY, // Today TOMORROW, AFTERTOMOROW, // Day after tomorrow DAY_COUNT, } WeatherDay; typedef struct TODAYDATA { uint16_t moonicon; // Moon phase icon index uint16_t pressure; // Air pressure uint16_t humidity; // Humidity percentage uint8_t sunraise[6]; // Sunrise time string "HH:MM" uint8_t sunset[6]; // Sunset time string "HH:MM" uint8_t lunar[16]; // Lunar date string } TodayData; typedef struct WEATHER { uint8_t date; // Day of month char day_temp; // Daytime temperature char night_temp; // Nighttime temperature uint16_t day_icon; // Daytime weather icon uint16_t night_icon; // Nighttime weather icon } Weather; ``` ## Bitmap Format MoWatch uses **horizontal 8-point left-high-bit encoding**: ```c // For a 120px wide image: int16_t byteWidth = (120 + 7) / 8; // = 15 bytes per row // To check if pixel (x, y) is black: if (bitmap[y * byteWidth + x / 8] & (128 >> (x & 7))) { // pixel is black } ``` ## Project Structure ``` app_projects/ ├── include/ │ └── header.h # SDK header (from skill sdk/) ├── libs/ │ ├── init_datas.c # SDK init (from skill sdk/) │ ├── tiny-json.c # JSON library (optional) │ └── syscall_gcc.txt # Syscall definitions (from skill sdk/) └── app_yourapp/ ├── code/ │ ├── app_main.c # Your main code │ └── graphics.h # Your bitmap data (optional) └── gcc/ ├── Makefile # From skill templates/ ├── app.ld # From skill templates/ └── createmwa.py # From skill templates/ ``` ## Complete API Reference ### Drawing Functions ```c // Clear entire screen void eink_clear(uint16_t color); // Draw single pixel void eink_drawpixel(uint16_t x, uint16_t y, uint16_t color); // Draw line void eink_drawline(uint16_t start_x, uint16_t start_y, uint16_t end_x, uint16_t end_y, uint16_t color); // Draw dashed line void eink_drawdashedline(uint16_t start_x, uint16_t start_y, uint16_t end_x, uint16_t end_y, uint16_t color); // Draw rectangle (MODE_EMPTY=outline, MODE_FILL=filled) void eink_drawrect(uint16_t start_x, uint16_t start_y, uint16_t end_x, uint16_t end_y, uint16_t color, uint8_t fill_mode); // Draw circle void eink_drawcircle(int x_center, int y_center, int radius, int color, int fill_mode); // Draw bitmap - THE MOST IMPORTANT FUNCTION! // x, y: top-left position // w, h: width and height in pixels // data[]: bitmap array (horizontal 8-point left-high-bit) // color: drawing color (BLACK or WHITE) // transparent: 0=draw both colors, 1=only draw foreground void eink_draw_bmp(uint16_t x, uint16_t y, uint16_t w, uint16_t h, const uint8_t data[], uint16_t color, uint8_t transparent); // Draw ASCII string // Returns: width of drawn string uint16_t eink_drawstr(uint16_t x, uint16_t y, const unsigned char *chr, uint16_t size, uint16_t color); // Draw Chinese string (UTF-8) uint16_t eink_drawchstr(uint16_t x, uint16_t y, const unsigned char *chr, uint16_t color); // Draw string within rectangle bounds uint16_t eink_draw_rectstr(const unsigned char *chr, uint16_t start_x, uint16_t start_y, uint16_t end_x, uint16_t end_y, uint16_t color); // Set screen rotation void eink_set_rotate(Rotate rotate); // Get weather icon bitmap (32x32) into buffer void get_weather_icon(uint16_t iconidx, uint8_t *buffer); ``` ### Time Functions ```c int RTC_getYear(void); // Full year (e.g., 2024) int RTC_getMon(void); // Month 1-12 int RTC_getDay(void); // Day 1-31 int RTC_getHour(void); // Hour 0-23 int RTC_getMin(void); // Minute 0-59 int RTC_getSec(void); // Second 0-59 int RTC_getWeek(void); // Day of week (0=Sunday) int RTC_getTimeStamp(void); // Unix timestamp ``` ### System Functions ```c // Get battery percentage (0-100) uint8_t watch_app_battpercent(void); // Exit app, return to main menu void watch_app_exit(void); // Set update interval for onUpdate() callback (in milliseconds) void set_update_interval(uint32_t interval); // Get current update interval uint32_t get_update_interval(void); // Log message (for debugging) void watch_app_log(char* log); // Get Bluetooth connection state BlueState watch_app_bluestate(void); // Check if weather data is available uint8_t watch_app_isweather_ok(void); // Get today's data (sunrise, sunset, lunar, etc.) TodayData watch_app_getToday(void); // Get weather for specified day Weather watch_app_getweather(WeatherDay day); // HTTP request (async, result via callback) void watch_app_http_req(const char* url, void(req_callback)(char*)); ``` ### File Operations ```c // Read file // Returns: bytes read uint32_t watch_app_read_file(const uint8_t* file_name, uint8_t* buffer, uint32_t len, uint32_t seekofs); // Write file // fa_mode: FA_CREATE_ALWAYS, FA_OPEN_APPEND, etc. uint32_t watch_app_write_file(const uint8_t* file_name, uint8_t* buffer, uint32_t len, uint32_t seekofs, uint8_t fa_mode); // Delete file uint8_t watch_app_delete_file(const uint8_t* file_name); // Create directory uint8_t watch_app_mkdir(const uint8_t* dir); ``` ### Memory Functions ```c // Allocate memory (use sparingly - only 4K RAM!) void *m_malloc(uint32_t size); // Free memory void m_free(void *ptr); ``` ### Utility Functions ```c // Format string (like sprintf) void co_sprintf(char *out, const char *format, ...); // Get UTF-8 string length uint16_t utf_len(const unsigned char *chr); // Random number int rand(void); void srand(unsigned int seed); ``` ### Dialog Functions ```c // Show message dialog with OK/Cancel // submit callback receives: 1=OK, 0=Cancel void create_msg_dialog(const uint8_t* title, const uint8_t* msg, void (*submit)(uint8_t ok)); // Show menu dialog void create_menu_dialog(const char* title, const char** menu_item_names, const uint8_t count, void (*submit)(uint8_t confirm)); // Show number picker dialog void create_picker_dialog(uint8_t num, const uint8_t* nums, const uint8_t count, void (*submit)(uint8_t data)); ``` ## App Entry Points ```c #include "header.h" // Called when screen needs to be drawn void onDraw(void) { eink_clear(WHITE); // Draw your UI here } // Called when button is pressed // Return update type to trigger screen refresh UpdateType onKey(ButtonType key) { switch(key) { case KEY_BACK: watch_app_exit(); break; case KEY_UP: // Handle up button break; case KEY_DOWN: // Handle down button break; } return PART_UPDATE; // or NONE_UPDATE, FULL_UPDATE } // Called periodically based on set_update_interval() UpdateType onUpdate(int delta) { static uint8_t lastmin = 61; if (lastmin != RTC_getMin()) { lastmin = RTC_getMin(); return PART_UPDATE; // Refresh screen when minute changes } return NONE_UPDATE; } // App initialization - REQUIRED void app_init(intptr_t *draw_ptr_t, intptr_t *onkey_ptr_t, intptr_t *update_ptr_t, intptr_t* func_arr) { __initialize_datas(func_arr); *draw_ptr_t = (intptr_t)onDraw; *onkey_ptr_t = (intptr_t)onKey; *update_ptr_t = (intptr_t)onUpdate; // Initialize your variables here set_update_interval(1000); // Check every 1 second } ``` ## Complete Minimal Example ```c // app_main.c - Simple digital clock using eink_drawstr #include "header.h" void onDraw(void) { eink_clear(WHITE); char buf[32]; // Draw time (large, centered) co_sprintf(buf, "%02d:%02d", RTC_getHour(), RTC_getMin()); eink_drawstr(50, 80, (unsigned char*)buf, 32, BLACK); // Draw date co_sprintf(buf, "%04d-%02d-%02d", RTC_getYear(), RTC_getMon(), RTC_getDay()); eink_drawstr(40, 130, (unsigned char*)buf, 16, BLACK); // Draw battery co_sprintf(buf, "BAT:%d%%", watch_app_battpercent()); eink_drawstr(140, 5, (unsigned char*)buf, 12, BLACK); } UpdateType onKey(ButtonType key) { if (key == KEY_BACK || key == KEY_CENTER) { watch_app_exit(); } return NONE_UPDATE; } UpdateType onUpdate(int delta) { static uint8_t lastmin = 61; if (lastmin != RTC_getMin()) { lastmin = RTC_getMin(); if (RTC_getMin() % 5 == 0) { return FULL_UPDATE; } return PART_UPDATE; } return NONE_UPDATE; } void app_init(intptr_t *draw_ptr_t, intptr_t *onkey_ptr_t, intptr_t *update_ptr_t, intptr_t* func_arr) { __initialize_datas(func_arr); *draw_ptr_t = (intptr_t)onDraw; *onkey_ptr_t = (intptr_t)onKey; *update_ptr_t = (intptr_t)onUpdate; set_update_interval(1000); } ``` ## Building with Docker
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen