DTC and SCI improvements
This commit is contained in:
129
h8536/dtc.py
Normal file
129
h8536/dtc.py
Normal 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,
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user