1
0

DTC and SCI improvements

This commit is contained in:
Aiden
2026-05-25 14:22:32 +10:00
parent 62d1c3c876
commit 80819448cf
21 changed files with 13823 additions and 86 deletions

129
h8536/dtc.py Normal file
View File

@@ -0,0 +1,129 @@
from __future__ import annotations
from typing import TypedDict
from .formatting import h16
from .memory import region_for
from .rom import Rom
from .tables import IO_REGISTERS
DTC_REGISTER_INFO_SIZE = 8
DTC_RESERVED_MODE_MASK = 0x1FFF
class DtcEndpointInfo(TypedDict):
address: int
text: str
name: str | None
region: str
increment: bool
increment_step: int
class DtcModeInfo(TypedDict):
raw: int
size: str
bytes_per_transfer: int
source_increment: bool
destination_increment: bool
source_increment_step: int
destination_increment_step: int
reserved: int
reserved_set: bool
class DtcCountInfo(TypedDict):
raw: int
transfers: int
bytes: int
zero_means_65536: bool
class DtcRegisterInfo(TypedDict, total=False):
address: int
valid: bool
error: str
dtmr: int
dtsr: int
dtdr: int
dtcr: int
mode: DtcModeInfo
source: DtcEndpointInfo
destination: DtcEndpointInfo
count: DtcCountInfo
def _endpoint(address: int, increment: bool, increment_step: int) -> DtcEndpointInfo:
name = IO_REGISTERS.get(address)
return {
"address": address,
"text": name or h16(address),
"name": name,
"region": region_for(address).name,
"increment": increment,
"increment_step": increment_step if increment else 0,
}
def _mode(dtmr: int) -> DtcModeInfo:
size = "word" if dtmr & 0x8000 else "byte"
bytes_per_transfer = 2 if size == "word" else 1
source_increment = bool(dtmr & 0x4000)
destination_increment = bool(dtmr & 0x2000)
source_step = bytes_per_transfer if source_increment else 0
destination_step = bytes_per_transfer if destination_increment else 0
reserved = dtmr & DTC_RESERVED_MODE_MASK
return {
"raw": dtmr,
"size": size,
"bytes_per_transfer": bytes_per_transfer,
"source_increment": source_increment,
"destination_increment": destination_increment,
"source_increment_step": source_step,
"destination_increment_step": destination_step,
"reserved": reserved,
"reserved_set": reserved != 0,
}
def decode_dtc_register_info(rom: Rom, address: int) -> DtcRegisterInfo:
"""Decode the four-word DTMR/DTSR/DTDR/DTCR block pointed to by a DTC vector."""
end = address + DTC_REGISTER_INFO_SIZE - 1
if end > 0xFFFF:
return {
"address": address,
"valid": False,
"error": f"register information block {h16(address)}+{DTC_REGISTER_INFO_SIZE} exceeds page 0",
}
if not rom.contains(address, DTC_REGISTER_INFO_SIZE):
return {
"address": address,
"valid": False,
"error": f"register information block {h16(address)}-{h16(end)} is outside ROM image",
}
dtmr = rom.u16(address)
dtsr = rom.u16(address + 2)
dtdr = rom.u16(address + 4)
dtcr = rom.u16(address + 6)
mode = _mode(dtmr)
transfers = 0x10000 if dtcr == 0 else dtcr
return {
"address": address,
"valid": True,
"dtmr": dtmr,
"dtsr": dtsr,
"dtdr": dtdr,
"dtcr": dtcr,
"mode": mode,
"source": _endpoint(dtsr, mode["source_increment"], mode["source_increment_step"]),
"destination": _endpoint(dtdr, mode["destination_increment"], mode["destination_increment_step"]),
"count": {
"raw": dtcr,
"transfers": transfers,
"bytes": transfers * mode["bytes_per_transfer"],
"zero_means_65536": dtcr == 0,
},
}