Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ Commit messages follow the [Conventional Commits](https://www.conventionalcommit

**Scopes** (optional but enforced): if provided, the scope **must** be one of the allowed values. The scope is recommended for driver-specific changes but can be omitted for cross-cutting changes.

- Driver scopes: `apds9960`, `bme280`, `bq27441`, `daplink_bridge`, `daplink_flash`, `gc9a01`, `hts221`, `im34dt05`, `ism330dl`, `lis2mdl`, `mcp23009e`, `ssd1327`, `steami_config`, `vl53l1x`, `wsen-hids`, `wsen-pads`
- Driver scopes: `apds9960`, `bme280`, `bq27441`, `daplink_bridge`, `daplink_flash`, `gc9a01`, `hts221`, `im34dt05`, `ism330dl`, `lis2mdl`, `mcp23009e`, `ssd1327`, `steami_config`, `vl53l1x`, `wsen-hids`, `wsen-pads`, `steami_screen`
- Domain scopes: `ci`, `docs`, `style`, `tests`, `tooling`

### Examples
Expand Down
1 change: 1 addition & 0 deletions commitlint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ module.exports = {
'style',
'tests',
'tooling',
'steami_screen'
],
],
'type-enum': [
Expand Down
Empty file added lib/steami_screen/README.md
Empty file.
32 changes: 32 additions & 0 deletions lib/steami_screen/examples/watch.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""
Tutorial 09 — Analog Watch
Displays an analog clock face using the built-in RTC.
"""

import time

import ssd1327
from machine import RTC, SPI, Pin
from steami_screen import Screen, SSD1327Display

# --- Screen setup ---
spi = SPI(1)
dc = Pin("DATA_COMMAND_DISPLAY")
res = Pin("RST_DISPLAY")
cs = Pin("CS_DISPLAY")

display = SSD1327Display(ssd1327.WS_OLED_128X128_SPI(spi, dc, res, cs))
screen = Screen(display)

# --- RTC setup ---
rtc = RTC()

# --- Main loop ---
while True:
_, _, _, _, h, m, s, _ = rtc.datetime()

screen.clear()
screen.watch(h, m, s)
screen.show()

time.sleep(0.5)
6 changes: 6 additions & 0 deletions lib/steami_screen/manifest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
metadata(
description="Library for controlling the STeaMi round display.",
version="0.0.1",
)

package("steami_screen")
33 changes: 33 additions & 0 deletions lib/steami_screen/steami_screen/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
from steami_screen.colors import rgb_to_gray4, rgb_to_rgb8, rgb_to_rgb565
from steami_screen.device import (
BLACK,
BLUE,
DARK,
GRAY,
GREEN,
LIGHT,
RED,
WHITE,
YELLOW,
Screen,
)
from steami_screen.gc9a01 import GC9A01Display
from steami_screen.sssd1327 import SSD1327Display

__all__ = [
"BLACK",
"BLUE",
"DARK",
"GRAY",
"GREEN",
"LIGHT",
"RED",
"WHITE",
"YELLOW",
"GC9A01Display",
"SSD1327Display",
"Screen",
"rgb_to_gray4",
"rgb_to_rgb8",
"rgb_to_rgb565",
]
49 changes: 49 additions & 0 deletions lib/steami_screen/steami_screen/colors.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
"""
Color conversion utilities for STeaMi display backends.

Colors are represented as RGB tuples (r, g, b) with values 0-255.
Each backend converts to its native format:
- SSD1327 : grayscale 4-bit (0-15)
- GC9A01 : RGB565 (16-bit)
- Simulator: RGB tuple (pass-through)

All functions accept legacy int values for backward compatibility.
"""


def rgb_to_gray4(color):
"""Convert an RGB tuple to a 4-bit grayscale value (0-15).

Uses BT.601 luminance: Y = 0.299*R + 0.587*G + 0.114*B
Accepts int for backward compatibility (returned as-is, clamped to 0-15).
"""
if isinstance(color, int):
return max(0, min(15, color))
r, g, b = color
luminance = (r * 77 + g * 150 + b * 29) >> 8 # 0-255
return luminance >> 4 # 0-15


def rgb_to_rgb565(color):
"""Convert an RGB tuple to a 16-bit RGB565 integer.

Accepts int for backward compatibility (treated as gray4, expanded).
"""
if isinstance(color, int):
g = max(0, min(15, color)) * 17 # 0-255
r, b = g, g
else:
r, g, b = color
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3)


def rgb_to_rgb8(color):
"""Convert a color to an RGB tuple (r, g, b).

If already a tuple, returns it unchanged.
Accepts int for backward compatibility (treated as gray4, expanded).
"""
if isinstance(color, int):
v = max(0, min(15, color)) * 17 # 0-255
return (v, v, v)
return color
Loading
Loading