Emualtor improements
This commit is contained in:
@@ -11,6 +11,9 @@ from .constants import (
|
||||
SCI1_SSR,
|
||||
SCI1_TDR,
|
||||
SCI_SCR_TE,
|
||||
SCI_SSR_FER,
|
||||
SCI_SSR_ORER,
|
||||
SCI_SSR_PER,
|
||||
SCI_SSR_RDRF,
|
||||
SCI_SSR_TDRE,
|
||||
)
|
||||
@@ -34,6 +37,8 @@ class SCI1:
|
||||
- SCR bit 7 TIE, bit 6 RIE, bit 5 TE, bit 4 RE.
|
||||
- SSR bit 7 TDRE, bit 6 RDRF, bits 5..3 ORER/FER/PER.
|
||||
- Software normally writes TDR after TDRE=1, then clears SSR.TDRE.
|
||||
- SSR status flags are R/(W)*: writing 0 clears a latched flag, while
|
||||
writing 1 leaves the hardware-owned flag unchanged.
|
||||
"""
|
||||
|
||||
smr: int = 0x00
|
||||
@@ -47,6 +52,8 @@ class SCI1:
|
||||
tx_frames: list[bytes] = field(default_factory=list)
|
||||
_frame_buffer: bytearray = field(default_factory=bytearray)
|
||||
tx_ready_delay: int = 0
|
||||
tx_ready_ticks: int = 2
|
||||
_tx_ready_pending: bool = False
|
||||
|
||||
def read(self, address: int) -> int:
|
||||
if address == SCI1_SMR:
|
||||
@@ -75,10 +82,7 @@ class SCI1:
|
||||
self.tdr = value
|
||||
self._write_tdr(value)
|
||||
elif address == SCI1_SSR:
|
||||
# The real SSR is R/(W)*: writable zeroes clear latched flags after
|
||||
# the required read sequence. This scaffold applies zero bits
|
||||
# directly so ROM BCLR/BSET style accesses can be modeled.
|
||||
self.ssr = value
|
||||
self._write_ssr(value)
|
||||
elif address == SCI1_RDR:
|
||||
self.rdr = value
|
||||
else:
|
||||
@@ -92,10 +96,14 @@ class SCI1:
|
||||
if len(self._frame_buffer) == len(HEARTBEAT_FRAME):
|
||||
self.tx_frames.append(bytes(self._frame_buffer))
|
||||
self._frame_buffer.clear()
|
||||
self.ssr |= SCI_SSR_TDRE
|
||||
self.tx_ready_delay = 2
|
||||
self.tx_ready_delay = max(0, self.tx_ready_ticks)
|
||||
self._tx_ready_pending = True
|
||||
self.tx_events.append(SciTxEvent(SCI1_TDR, value, self.scr, self.ssr, emitted))
|
||||
|
||||
def _write_ssr(self, value: int) -> None:
|
||||
writable_zero_flags = SCI_SSR_TDRE | SCI_SSR_RDRF | SCI_SSR_ORER | SCI_SSR_FER | SCI_SSR_PER
|
||||
self.ssr = (self.ssr & (writable_zero_flags & value)) | (value & ~writable_zero_flags)
|
||||
|
||||
def inject_rx(self, value: int) -> None:
|
||||
self.rdr = value & 0xFF
|
||||
self.ssr |= SCI_SSR_RDRF
|
||||
@@ -104,7 +112,8 @@ class SCI1:
|
||||
return HEARTBEAT_FRAME in self.tx_frames
|
||||
|
||||
def tick(self) -> None:
|
||||
if self.tx_ready_delay:
|
||||
if self._tx_ready_pending and self.tx_ready_delay:
|
||||
self.tx_ready_delay -= 1
|
||||
if self.tx_ready_delay == 0:
|
||||
self.ssr |= SCI_SSR_TDRE
|
||||
if self._tx_ready_pending and self.tx_ready_delay == 0 and not (self.ssr & SCI_SSR_TDRE):
|
||||
self.ssr |= SCI_SSR_TDRE
|
||||
self._tx_ready_pending = False
|
||||
|
||||
Reference in New Issue
Block a user