LCD emulation
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from .lcd import LCD_E_CLOCK_DATA, LCD_E_CLOCK_STATUS
|
||||
from .lcd import LCD, LCD_E_CLOCK_DATA, LCD_E_CLOCK_STATUS, LCD_LINE_WIDTH
|
||||
from .p9_bus import P9_ACK_BIT, P9_STROBE_BIT, P9Bus, P9StrobeEvent
|
||||
|
||||
__all__ = [
|
||||
"LCD_E_CLOCK_DATA",
|
||||
"LCD_E_CLOCK_STATUS",
|
||||
"LCD",
|
||||
"LCD_LINE_WIDTH",
|
||||
"P9_ACK_BIT",
|
||||
"P9_STROBE_BIT",
|
||||
"P9Bus",
|
||||
|
||||
@@ -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",
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user