parent
c67c467486
commit
c5071bf1ca
@ -0,0 +1,449 @@ |
||||
// =============================================================================
|
||||
// Mono Display File Format - type definitions
|
||||
// Spec: Mono Display File Format Specification
|
||||
// =============================================================================
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Enums
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export enum FileVersion { |
||||
/** Illegal - must not appear in a valid file */ |
||||
Illegal = 0, |
||||
/** Current specification version */ |
||||
V1 = 1, |
||||
} |
||||
|
||||
export enum SectionType { |
||||
/** List of drawn elements - always shown */ |
||||
ElementsAlways = 1, |
||||
/** List of drawn elements - shown only within a POSIX timestamp window */ |
||||
ElementsTimespan = 2, |
||||
/** U8G2-format custom font used by draw elements in this file */ |
||||
CustomFont = 32, |
||||
} |
||||
|
||||
export enum ElementType { |
||||
Image2D = 1, |
||||
Animation = 2, |
||||
HorizontalScroll = 3, |
||||
VerticalScroll = 4, |
||||
Line = 5, |
||||
ClippedText = 16, |
||||
HScrollText = 17, |
||||
/** |
||||
* Current time display. |
||||
* NOTE: the spec diagram labels this element "Type: 16", which collides with |
||||
* ClippedText. This is assumed to be a spec typo; 18 is used here as the |
||||
* probable intended value until the spec is corrected. |
||||
*/ |
||||
CurrentTime = 18, |
||||
} |
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Section flags (section types 1 and 2)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** Bit-field flags for ElementsAlways / ElementsTimespan sections. */ |
||||
export interface SectionFlags { |
||||
/** Bit 0 - render elements onto the front-side buffer. */ |
||||
drawFront?: boolean; |
||||
/** Bit 1 - render elements onto the back-side buffer. */ |
||||
drawBack?: boolean; |
||||
/** Bit 2 - clear targeted buffer(s) before drawing this section's elements. */ |
||||
clearBuffer?: boolean; |
||||
// Bits 3-15: reserved; writers MUST write 0.
|
||||
} |
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Scroll element flags (HorizontalScroll / VerticalScroll / HScrollText)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface ScrollElementFlags { |
||||
/** Bit 0 - wrap content endlessly. */ |
||||
endless?: boolean; |
||||
/** Bit 1 - reverse scroll direction. */ |
||||
invertDirection?: boolean; |
||||
/** Bit 2 - pad at start edge (left for H-scroll, top for V-scroll). */ |
||||
padStart?: boolean; |
||||
/** Bit 3 - pad at end edge (right for H-scroll, bottom for V-scroll). */ |
||||
padEnd?: boolean; |
||||
// Bits 4-7: reserved.
|
||||
} |
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// CurrentTime element flags
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface CurrentTimeFlags { |
||||
/** Bit 0 - use 12-hour clock (default 24-hour). */ |
||||
clock12h?: boolean; |
||||
/** Bit 1 - show hours. */ |
||||
showHours?: boolean; |
||||
/** Bit 2 - show minutes. */ |
||||
showMinutes?: boolean; |
||||
/** Bit 3 - show seconds. */ |
||||
showSeconds?: boolean; |
||||
// Bits 4-15: reserved.
|
||||
} |
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Line element flags
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface LineFlags { |
||||
/** Bit 0 - invert pixel values along the line. */ |
||||
invertPixels?: boolean; |
||||
// Bits 1-7: reserved.
|
||||
} |
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Font index helpers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/** |
||||
* Font index encoding: |
||||
* 0 .. 0x7FFF built-in font (device-specific; may not exist) |
||||
* 0x8000+ custom font embedded in this file |
||||
* 0x8000 = first CustomFont section |
||||
* 0x8001 = second, etc. |
||||
*/ |
||||
export type FontIndex = number; |
||||
|
||||
export const CUSTOM_FONT_BASE = 0x8000; |
||||
|
||||
/** Return true when fontIndex refers to a custom (in-file) font. */ |
||||
export function isCustomFont(fontIndex: FontIndex): boolean { |
||||
return fontIndex >= CUSTOM_FONT_BASE; |
||||
} |
||||
|
||||
/** Extract zero-based position of a custom font within the file. */ |
||||
export function customFontOrdinal(fontIndex: FontIndex): number { |
||||
return fontIndex - CUSTOM_FONT_BASE; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// User-facing element descriptors (MonoDisplayFile / builder input)
|
||||
// Pixels are 1 byte/pixel (0 = off, 1 = on) in the API; packed to 1bpp on
|
||||
// serialisation.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface Image2DElement { |
||||
type: ElementType.Image2D; |
||||
/** Row-major, 1 byte/pixel (0 = off, 1 = on). Packed to 1bpp on write. */ |
||||
pixels: Uint8Array; |
||||
width: number; |
||||
height: number; |
||||
xOffset?: number; // default 0
|
||||
yOffset?: number; // default 0
|
||||
} |
||||
|
||||
export interface AnimationFrameDescriptor { |
||||
/** 1 byte/pixel, same dimensions as the parent AnimationElement. */ |
||||
pixels: Uint8Array; |
||||
} |
||||
|
||||
export interface AnimationElement { |
||||
type: ElementType.Animation; |
||||
width: number; |
||||
height: number; |
||||
frames: AnimationFrameDescriptor[]; |
||||
/** |
||||
* Advance frame every (updateInterval + 1) ticks. |
||||
* 0 = every tick, 1 = every 2nd tick, ..., 65535 = every 65536th tick. |
||||
* Default 0. |
||||
*/ |
||||
updateInterval?: number; |
||||
xOffset?: number; |
||||
yOffset?: number; |
||||
} |
||||
|
||||
export interface HScrollElement { |
||||
type: ElementType.HorizontalScroll; |
||||
/** Viewport width in pixels. */ |
||||
width: number; |
||||
/** Viewport height in pixels. */ |
||||
height: number; |
||||
/** Scrolling content pixels (contentWidth × height), 1 byte/pixel. */ |
||||
pixels: Uint8Array; |
||||
contentWidth: number; |
||||
/** |
||||
* Scroll speed byte SS; moves (SS + 1) / 16 pixels per tick. |
||||
* Range 0-255. Default 0 (= 1/16 px/tick). |
||||
*/ |
||||
scrollSpeed?: number; |
||||
flags?: ScrollElementFlags; |
||||
xOffset?: number; |
||||
yOffset?: number; |
||||
} |
||||
|
||||
export interface VScrollElement { |
||||
type: ElementType.VerticalScroll; |
||||
/** Viewport width in pixels. */ |
||||
width: number; |
||||
/** Viewport height in pixels. */ |
||||
height: number; |
||||
/** Scrolling content pixels (width × contentHeight), 1 byte/pixel. */ |
||||
pixels: Uint8Array; |
||||
contentHeight: number; |
||||
/** Scroll speed byte SS; moves (SS + 1) / 16 pixels per tick. Default 0. */ |
||||
scrollSpeed?: number; |
||||
flags?: ScrollElementFlags; |
||||
xOffset?: number; |
||||
yOffset?: number; |
||||
} |
||||
|
||||
export interface LineElement { |
||||
type: ElementType.Line; |
||||
xOrigin: number; |
||||
yOrigin: number; |
||||
xTarget: number; |
||||
yTarget: number; |
||||
/** Reserved by spec; writers MUST write 0. */ |
||||
lineStyle?: number; |
||||
invertPixels?: boolean; // flags bit 0
|
||||
} |
||||
|
||||
export interface ClippedTextElement { |
||||
type: ElementType.ClippedText; |
||||
text: string; // UTF-8
|
||||
width: number; |
||||
height: number; |
||||
/** 0-32767 = built-in font; 0x8000+ = custom font in file. Default 0. */ |
||||
fontIndex?: FontIndex; |
||||
xOffset?: number; |
||||
yOffset?: number; |
||||
} |
||||
|
||||
export interface HScrollTextElement { |
||||
type: ElementType.HScrollText; |
||||
text: string; // UTF-8
|
||||
width: number; |
||||
height: number; |
||||
scrollSpeed?: number; // SS byte, default 0
|
||||
fontIndex?: FontIndex; |
||||
flags?: ScrollElementFlags; |
||||
xOffset?: number; |
||||
yOffset?: number; |
||||
} |
||||
|
||||
export interface CurrentTimeElement { |
||||
type: ElementType.CurrentTime; |
||||
width: number; |
||||
height: number; |
||||
/** 0-32767 = built-in font; 0x8000+ = custom font in file. Default 0. */ |
||||
fontIndex?: FontIndex; |
||||
/** |
||||
* UTC offset in whole minutes (signed 16-bit integer). |
||||
* e.g. UTC+5:30 → 330, UTC-8 → -480. |
||||
*/ |
||||
utcOffsetMinutes?: number; |
||||
flags?: CurrentTimeFlags; |
||||
xOffset?: number; |
||||
yOffset?: number; |
||||
} |
||||
|
||||
export type DrawElement = |
||||
| Image2DElement |
||||
| AnimationElement |
||||
| HScrollElement |
||||
| VScrollElement |
||||
| LineElement |
||||
| ClippedTextElement |
||||
| HScrollTextElement |
||||
| CurrentTimeElement; |
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Section descriptors (MonoDisplayFile / builder input)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface ElementsAlwaysDescriptor { |
||||
flags?: SectionFlags; |
||||
elements: DrawElement[]; |
||||
} |
||||
|
||||
export interface ElementsTimespanDescriptor { |
||||
flags?: SectionFlags; |
||||
elements: DrawElement[]; |
||||
/** POSIX timestamp (seconds) - section visible when now >= startTimestamp. */ |
||||
startTimestamp: bigint; |
||||
/** POSIX timestamp (seconds) - section visible when now < endTimestamp. */ |
||||
endTimestamp: bigint; |
||||
} |
||||
|
||||
export interface CustomFontDescriptor { |
||||
/** Raw U8G2 font data. */ |
||||
fontData: Uint8Array; |
||||
} |
||||
|
||||
/** |
||||
* Top-level descriptor passed to MonoDisplayFile. |
||||
* |
||||
* Sections are written in the order they appear here. |
||||
* Custom fonts MUST appear before any element that references them. |
||||
*/ |
||||
export interface MonoDisplayFileDescriptor { |
||||
/** Section type 1 - drawn every render tick. */ |
||||
elements_always?: DrawElement[] | ElementsAlwaysDescriptor; |
||||
/** Section type 2 - drawn only within the given timestamp window. */ |
||||
elements_timespan?: ElementsTimespanDescriptor[]; |
||||
/** Section type 32 - embedded U8G2 custom fonts. */ |
||||
custom_fonts?: CustomFontDescriptor[]; |
||||
} |
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// MonoFormat types (MonoDisplayParser output → renderer input)
|
||||
// Pixels are always unpacked (1 byte/pixel) after parsing.
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
export interface MonoFormatPixelImage { |
||||
/** Unpacked: 1 byte per pixel, 0 = off, 1 = on, row-major. */ |
||||
pixels: Uint8Array; |
||||
width: number; |
||||
height: number; |
||||
} |
||||
|
||||
export interface MonoFormatImage2D { |
||||
type: ElementType.Image2D; |
||||
xOffset: number; |
||||
yOffset: number; |
||||
image: MonoFormatPixelImage; |
||||
} |
||||
|
||||
export interface MonoFormatAnimation { |
||||
type: ElementType.Animation; |
||||
xOffset: number; |
||||
yOffset: number; |
||||
width: number; |
||||
height: number; |
||||
updateInterval: number; |
||||
frames: MonoFormatPixelImage[]; |
||||
} |
||||
|
||||
export interface MonoFormatScrollFlags { |
||||
endless: boolean; |
||||
invertDirection: boolean; |
||||
padStart: boolean; |
||||
padEnd: boolean; |
||||
} |
||||
|
||||
export interface MonoFormatHScroll { |
||||
type: ElementType.HorizontalScroll; |
||||
xOffset: number; |
||||
yOffset: number; |
||||
width: number; |
||||
height: number; |
||||
contentWidth: number; |
||||
scrollSpeed: number; |
||||
flags: MonoFormatScrollFlags; |
||||
content: MonoFormatPixelImage; |
||||
} |
||||
|
||||
export interface MonoFormatVScroll { |
||||
type: ElementType.VerticalScroll; |
||||
xOffset: number; |
||||
yOffset: number; |
||||
width: number; |
||||
height: number; |
||||
contentHeight: number; |
||||
scrollSpeed: number; |
||||
flags: MonoFormatScrollFlags; |
||||
content: MonoFormatPixelImage; |
||||
} |
||||
|
||||
export interface MonoFormatLine { |
||||
type: ElementType.Line; |
||||
xOrigin: number; |
||||
yOrigin: number; |
||||
xTarget: number; |
||||
yTarget: number; |
||||
lineStyle: number; |
||||
invertPixels: boolean; |
||||
} |
||||
|
||||
export interface MonoFormatClippedText { |
||||
type: ElementType.ClippedText; |
||||
xOffset: number; |
||||
yOffset: number; |
||||
width: number; |
||||
height: number; |
||||
fontIndex: FontIndex; |
||||
text: string; |
||||
} |
||||
|
||||
export interface MonoFormatHScrollText { |
||||
type: ElementType.HScrollText; |
||||
xOffset: number; |
||||
yOffset: number; |
||||
width: number; |
||||
height: number; |
||||
scrollSpeed: number; |
||||
fontIndex: FontIndex; |
||||
flags: MonoFormatScrollFlags; |
||||
text: string; |
||||
} |
||||
|
||||
export interface MonoFormatCurrentTimeFlags { |
||||
clock12h: boolean; |
||||
showHours: boolean; |
||||
showMinutes: boolean; |
||||
showSeconds: boolean; |
||||
} |
||||
|
||||
export interface MonoFormatCurrentTime { |
||||
type: ElementType.CurrentTime; |
||||
xOffset: number; |
||||
yOffset: number; |
||||
width: number; |
||||
height: number; |
||||
fontIndex: FontIndex; |
||||
/** UTC offset in minutes (signed). */ |
||||
utcOffsetMinutes: number; |
||||
flags: MonoFormatCurrentTimeFlags; |
||||
} |
||||
|
||||
export type MonoFormatElement = |
||||
| MonoFormatImage2D |
||||
| MonoFormatAnimation |
||||
| MonoFormatHScroll |
||||
| MonoFormatVScroll |
||||
| MonoFormatLine |
||||
| MonoFormatClippedText |
||||
| MonoFormatHScrollText |
||||
| MonoFormatCurrentTime; |
||||
|
||||
export interface MonoFormatSectionFlags { |
||||
drawFront: boolean; |
||||
drawBack: boolean; |
||||
clearBuffer: boolean; |
||||
} |
||||
|
||||
export interface MonoFormatElementsAlways { |
||||
sectionType: SectionType.ElementsAlways; |
||||
flags: MonoFormatSectionFlags; |
||||
elements: MonoFormatElement[]; |
||||
} |
||||
|
||||
export interface MonoFormatElementsTimespan { |
||||
sectionType: SectionType.ElementsTimespan; |
||||
flags: MonoFormatSectionFlags; |
||||
startTimestamp: bigint; // POSIX seconds
|
||||
endTimestamp: bigint; |
||||
elements: MonoFormatElement[]; |
||||
} |
||||
|
||||
export interface MonoFormatCustomFont { |
||||
sectionType: SectionType.CustomFont; |
||||
/** Raw U8G2 font data (actual bytes, not padded). */ |
||||
fontData: Uint8Array; |
||||
} |
||||
|
||||
export type MonoFormatSection = |
||||
| MonoFormatElementsAlways |
||||
| MonoFormatElementsTimespan |
||||
| MonoFormatCustomFont; |
||||
|
||||
/** Top-level MonoDisplayParser output. */ |
||||
export interface MonoFormatFile { |
||||
sections: MonoFormatSection[]; |
||||
} |
||||
Loading…
Reference in new issue