1
0

LCD emulation

This commit is contained in:
Aiden
2026-05-25 21:33:19 +10:00
parent e141f3b30d
commit 191b72d418
7 changed files with 113 additions and 11 deletions

View File

@@ -1,5 +1,69 @@
from __future__ import annotations
from dataclasses import dataclass, field
LCD_E_CLOCK_STATUS = 0xF200
LCD_E_CLOCK_DATA = 0xF201
LCD_LINE_WIDTH = 16
LCD_LINE_STARTS = (0x00, 0x40, 0x10, 0x50)
LCD_DDRAM_SIZE = 0x80
@dataclass
class LCD:
ddram: bytearray = field(default_factory=lambda: bytearray([0x20] * LCD_DDRAM_SIZE))
cursor: int = 0
data_latch: int = 0
command_latch: int = 0
def read_status(self) -> int:
return self.cursor & 0x7F
def read_data(self) -> int:
return self.data_latch & 0xFF
def write_command(self, value: int) -> None:
value &= 0xFF
self.command_latch = value
if value & 0x80:
self.cursor = value & 0x7F
elif value == 0x01:
self.ddram[:] = bytes([0x20]) * LCD_DDRAM_SIZE
self.cursor = 0
elif value == 0x02:
self.cursor = 0
def write_data(self, value: int) -> None:
value &= 0xFF
self.data_latch = value
if 0 <= self.cursor < LCD_DDRAM_SIZE:
self.ddram[self.cursor] = value
self.cursor = (self.cursor + 1) & 0x7F
def line_text(self, line: int, width: int = LCD_LINE_WIDTH) -> str:
if not 0 <= line < len(LCD_LINE_STARTS):
raise ValueError(f"LCD line out of range: {line}")
start = LCD_LINE_STARTS[line]
return "".join(_display_char(self.ddram[(start + offset) & 0x7F]) for offset in range(width))
def display_lines(self, lines: int = 4, width: int = LCD_LINE_WIDTH) -> list[str]:
return [self.line_text(line, width) for line in range(lines)]
def display_text(self, lines: int = 4, width: int = LCD_LINE_WIDTH) -> str:
return " | ".join(self.display_lines(lines, width))
def _display_char(value: int) -> str:
return chr(value) if 0x20 <= value <= 0x7E else "."
__all__ = [
"LCD",
"LCD_DDRAM_SIZE",
"LCD_E_CLOCK_DATA",
"LCD_E_CLOCK_STATUS",
"LCD_LINE_STARTS",
"LCD_LINE_WIDTH",
]