5.7 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project Overview
This is a novelty Garmin Connect IQ watchface that displays time as decimal day progress (French Revolutionary Time style) instead of traditional 12/24 hour format. The day is divided into 10 equal parts, with time displayed as a decimal from 0.0 to 10.0.
Key Concept: The watchface converts standard time to decimal using the formula:
decimalTime = (hours + minutes/60 + seconds/3600) / 24 * 10
This means:
- Midnight (00:00) → 0.0
- 6:00 AM → 2.5
- Noon (12:00) → 5.0
- 6:00 PM → 7.5
- End of day → 10.0
Development Commands
Building the Watchface
The project uses the Garmin Connect IQ SDK. You need the SDK installed with $SDK_PATH environment variable set.
Build for simulator:
$SDK_PATH/bin/monkeyc \
-o bin/MetricWatchFace.prg \
-f monkey.jungle \
-y $SDK_PATH/bin/developer_key
Run in simulator:
$SDK_PATH/bin/connectiq
# Then load the generated .prg file in the simulator
Build for specific device (example for Fenix 7):
$SDK_PATH/bin/monkeyc \
-o bin/MetricWatchFace.prg \
-f monkey.jungle \
-d fenix7 \
-y $SDK_PATH/bin/developer_key
Note: The project uses monkey.jungle for build configuration, which references manifest.xml for project settings.
Architecture
Core Components
DecimalWatchFaceApp.mc (source/DecimalWatchFaceApp.mc:4-23)
- Application entry point extending
Application.AppBase - Minimal setup - primarily returns the watchface view
- No complex application state management
DecimalWatchFaceView.mc (source/DecimalWatchFaceView.mc:8-201)
- Main watchface implementation extending
WatchUi.WatchFace - Handles all rendering and time calculation logic
- Key methods:
onUpdate(dc)- Main render loop, called every second when activecomputeDecimalTime(clockTime)- Converts standard time to decimal (0.0-10.0)drawWatchFace(dc)- Renders the analog face with 10 divisions, tick marks, and numbersdrawHand(dc, decimalTime)- Draws both hour and minute handsdrawSingleHand(...)- Helper for rendering individual hands as filled polygonsdrawDigitalTime(dc, decimalTime)- Displays decimal time as text
Rendering Architecture
The watchface uses programmatic drawing (no XML layouts). All graphics are drawn using Monkey C Graphics API:
- Watchface Circle: 100 tick marks drawn in a loop (10 major at whole numbers 0-9, 90 minor at 0.1 intervals)
- Two Hands:
- Hour hand (red, shorter, wider): Shows which decimal unit (0-9), completes one rotation per day
- Minute hand (white, longer, thinner): Shows fractional part within current decimal unit, completes 10 rotations per day
- Digital Display: Shows exact decimal time at bottom (formatted to 2 decimal places)
The hand rotation uses trigonometry with angles calculated from decimal time, offset by -90° to start at top (12 o'clock position).
Device Support
The manifest (manifest.xml) targets 57 modern Garmin devices including:
- Fenix series (6, 7, 8, Epix 2)
- Forerunner series (255, 265, 645, 945, 955, 965, 970)
- Vivoactive series (3, 4, 5, 6)
- Venu series (2 Plus, 3, 4)
All devices require Connect IQ API level 3.2.0 or higher.
Project Structure
MetricWatchFace/
├── manifest.xml # App metadata, device compatibility
├── monkey.jungle # Build configuration
├── source/
│ ├── DecimalWatchFaceApp.mc # Application entry point
│ └── DecimalWatchFaceView.mc # Main watchface view and rendering
└── resources/
├── drawables/
│ ├── drawables.xml # Drawable resource definitions
│ └── launcher_icon.png # App icon (placeholder)
└── strings/
└── strings.xml # Localized strings
Important Implementation Details
Time Calculation Edge Cases
- The decimal time formula ensures smooth progression from 0.0 to 10.0
- The fractional part extraction (
decimalTime - decimalTime.toNumber()) is used for the minute hand - Both hands update every second when the watchface is active
Drawing Performance
- The watchface redraws completely on each
onUpdate()call - 100 tick marks are drawn in every frame (major optimization opportunity)
- Hands are drawn as filled polygons using triangle geometry
- Center dot is redrawn after hands to ensure it's on top
Sleep Mode Handling
onEnterSleep()andonExitSleep()are currently empty- In sleep mode, the system reduces update frequency automatically
- Consider implementing reduced complexity rendering for sleep mode
Known Technical Debt
From IMPROVEMENT_IDEAS.md:
- Launcher icon is currently a placeholder PNG
- No screen type optimization (MIP vs AMOLED)
- No low power mode implementation
- Hand polygon drawing could be optimized
- No error handling for edge cases
- No unit tests for time conversion
Monkey C Specifics
Language: Monkey C (Garmin's proprietary language, similar to Java/C) Key APIs used:
Toybox.WatchUi.WatchFace- Base class for watchfacesToybox.Graphics- Drawing primitives (drawLine, fillPolygon, drawText, etc.)Toybox.System- System functions (getClockTime)Toybox.Time/Toybox.Time.Gregorian- Time utilitiesToybox.Lang/Toybox.Math- Language and math utilities
Common patterns:
- Drawing context (
dc) is passed to all render methods - Colors use
Graphics.COLOR_*constants - Coordinates are in pixels, origin at top-left
- All trigonometry uses radians (convert with
Math.toRadians())