feat: types from spec

pull/1/head
flop 4 weeks ago
parent c67c467486
commit c5071bf1ca
  1. 449
      ts/src/types.ts

@ -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…
Cancel
Save