tmp94c241: Add serial port sub-device with I/O interface mode#15015
tmp94c241: Add serial port sub-device with I/O interface mode#15015felipesanches wants to merge 3 commits intomamedev:masterfrom
Conversation
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.
2fa212e to
4555d55
Compare
| // 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. |
There was a problem hiding this comment.
Doesn't tx interrupt happen at the end of the stop bit rather than the last data bit?
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
|
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. |

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.