Skip to content

tmp94c241: Add serial port sub-device with I/O interface mode#15015

Open
felipesanches wants to merge 3 commits intomamedev:masterfrom
felipesanches:kn5000_pr4_serial
Open

tmp94c241: Add serial port sub-device with I/O interface mode#15015
felipesanches wants to merge 3 commits intomamedev:masterfrom
felipesanches:kn5000_pr4_serial

Conversation

@felipesanches
Copy link
Contributor

Replace the inline serial stubs (which just instantly set TX-complete)
with a proper sub-device implementation supporting:

  • I/O interface mode (mode 0): Synchronous clocked serial using SCLK
    pin. Supports both internal (baud rate generator) and external
    (IOC=1) clock sources. TX double buffering with auto-load from
    buffer to shift register. Pre-outputs bit 0 on TXD before first
    clock edge so receiver can sample it on the rising edge.

  • Baud rate generator: Configurable via BRxCR register with divisor
    and clock source selection. Timer drives SCLK at the configured
    rate. Clock frequency derived from CPU clock.

  • TX/RX data callbacks: txd(), rxd(), sclk_out(), sclk_in() for
    connecting external devices to the serial ports.

  • tx_start callback: Signals the start of each byte transmission with
    the current PFFC pin function state, allowing connected devices to
    distinguish real transmissions from phantom ones.

The serial registers (SC0BUF/SC1BUF, SC0CR/SC1CR, SC0MOD/SC1MOD,
BR0CR/BR1CR) are now delegated to the sub-devices in the internal
memory map. TX-complete flags (INTES0/INTES1 bit 7) are set at
device_reset to indicate empty TX buffers at power-on.

UART modes (7/8/9-bit) are recognized but not yet implemented.

Also moves interrupt register indices from a file-scope enum to
public static constexpr members of tmp94c241_device.

Replace the inline serial stubs (which just instantly set TX-complete)
with a proper sub-device implementation supporting:

- I/O interface mode (mode 0): Synchronous clocked serial using SCLK
  pin. Supports both internal (baud rate generator) and external
  (IOC=1) clock sources. TX double buffering with auto-load from
  buffer to shift register. Pre-outputs bit 0 on TXD before first
  clock edge so receiver can sample it on the rising edge.

- Baud rate generator: Configurable via BRxCR register with divisor
  and clock source selection. Timer drives SCLK at the configured
  rate. Clock frequency derived from CPU clock.

- TX/RX data callbacks: txd(), rxd(), sclk_out(), sclk_in() for
  connecting external devices to the serial ports.

- tx_start callback: Signals the start of each byte transmission with
  the current PFFC pin function state, allowing connected devices to
  distinguish real transmissions from phantom ones.

The serial registers (SC0BUF/SC1BUF, SC0CR/SC1CR, SC0MOD/SC1MOD,
BR0CR/BR1CR) are now delegated to the sub-devices in the internal
memory map. TX-complete flags (INTES0/INTES1 bit 7) are set at
device_reset to indicate empty TX buffers at power-on.

UART modes (7/8/9-bit) are recognized but not yet implemented.

Also moves interrupt register indices from a file-scope enum to
public static constexpr members of tmp94c241_device.
Per galibert's review suggestion: defining the IRQ vector table as a
static const member of tmp94c241_device and providing the out-of-class
definition in class scope allows the INTE* constants to be referenced
without tmp94c241_device:: qualifiers in the initializer.

The nested struct is named irq_vector_entry. NUM_MASKABLE_IRQS is
replaced by std::size(irq_vector_map) directly at each use site inside
member functions.
// the ISR can write SC1BUF. In MAME's event-driven scheduler,
// CPU instructions run between timer ticks, so without this deferral
// the ISR would write SC1BUF (pre-outputting bit 0) BEFORE the
// trailing rising edge — corrupting bit 7 of every byte.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't tx interrupt happen at the end of the stop bit rather than the last data bit?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This implementation only supports the I/O interface mode, which is what I need for the Technics KN5000 control panel. There are 8 SCLK pulses per byte with no start or stop bits and INTTX fires after the last data bit.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there some kind of an error/warning if something tries to use an unimplemented mode? Personally I'd lean towards fatalerror() for that, having been on the wrong end of too many silent unimplemented failures in MAME, but even just a logerror() would be OK.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image

@felipesanches
Copy link
Contributor Author

One additional PR (which brings the Technics KN5000 driver to an interactive state as seen here two weeks ago with control panel HLE working) is waiting to be submitted after this one is merged.

I'd appreciate this PR being merged soon in case nobody could find anything else that may still need improvements.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants