From 080bf456d6635d14c9668bb6691fca04e0409f75 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 30 Apr 2023 21:10:59 +0300 Subject: [PATCH] inter-process serial port stability fix, status signal and break support. --- od-win32/serial_win32.cpp | 117 +++++++++++++++++++++++++++++++++----- 1 file changed, 102 insertions(+), 15 deletions(-) diff --git a/od-win32/serial_win32.cpp b/od-win32/serial_win32.cpp index 448ea8d7..bbb0e18e 100644 --- a/od-win32/serial_win32.cpp +++ b/od-win32/serial_win32.cpp @@ -49,13 +49,14 @@ struct sermap_buffer volatile uae_u32 active_write; volatile uae_u32 read_offset; volatile uae_u32 write_offset; - volatile uae_u16 data[SERMAP_SIZE]; + volatile uae_u32 data[SERMAP_SIZE]; }; static struct sermap_buffer *sermap1, *sermap2; static HANDLE sermap_handle; static uae_u8 *sermap_data; static bool sermap_master; static bool sermap_enabled; +static uae_u32 sermap_flags; static bool serloop_enabled; static bool serempty_enabled; static bool serxdevice_enabled; @@ -66,7 +67,7 @@ static int receive_buf_size, receive_buf_count; #define SER_MEMORY_MAPPING _T("WinUAE_Serial") -static void shmem_serial_send(uae_u16 data) +static void shmem_serial_send(uae_u32 data) { uae_u32 v; @@ -83,16 +84,16 @@ static void shmem_serial_send(uae_u16 data) v &= (SERMAP_SIZE - 1); sermap1->write_offset = v; } -static uae_u16 shmem_serial_receive(void) +static uae_u32 shmem_serial_receive(void) { uae_u32 v; - uae_u16 data; + uae_u32 data; sermap2->active_read = true; if (!sermap2->active_write) - return 0xffff; + return 0xffffffff; v = sermap2->read_offset; if (v == sermap2->write_offset) - return 0xffff; + return 0xffffffff; data = sermap2->data[v]; v++; v &= (SERMAP_SIZE - 1); @@ -103,6 +104,7 @@ static uae_u16 shmem_serial_receive(void) static void sermap_deactivate(void) { sermap_enabled = false; + sermap_flags = 0; if (sermap1) { sermap1->active_write = 0; sermap1->write_offset = sermap1->read_offset; @@ -604,8 +606,9 @@ static void checksend(void) return; } #ifdef SERIAL_MAP - if (sermap_data && sermap_enabled) + if (sermap_data && sermap_enabled) { shmem_serial_send(serdatshift); + } #endif #ifdef SERIAL_ENET if (serial_enet) { @@ -814,21 +817,62 @@ void serial_hsynchandler (void) } } - if (lastbitcycle_active_hsyncs > 0) + if (lastbitcycle_active_hsyncs > 0) { lastbitcycle_active_hsyncs--; + } #ifdef SERIAL_MAP - if (sermap2 && sermap_enabled && !data_in_serdatr) { - uae_u16 v = shmem_serial_receive(); - if (v != 0xffff) { - serdatr = v; + if (sermap2 && sermap_enabled) { + if (!data_in_serdatr) { + for (;;) { + uae_u32 v = shmem_serial_receive(); + if (v == 0xffffffff) { + break; + } + if (!(v & 0xffff0000)) { + serdatr = (uae_u16)v; + serial_rx_irq(); + break; + } else if ((v & 0x80000000) == 0x80000000) { + sermap_flags &= 0x0fff0000; + sermap_flags |= v & 0xffff; + } else if ((v & 0x40000000) == 0x40000000) { + if (v & (0x10000 | 0x20000)) { + sermap_flags &= ~(0x10000 | 0x20000); + sermap_flags |= v & (0x10000 | 0x20000); + break; + } + } + } + } + // break on + if (sermap_flags & 0x20000) { + break_in_serdatr = maxvpos; + } + if (break_in_serdatr) { + serdatr = 0; + if (break_delay == 0) { + serial_rx_irq(); + break_delay = SERIAL_BREAK_TRANSMIT_DELAY; + } + if (break_delay > 0) { + break_delay--; + } + } + // break off + if (break_in_serdatr == 1) { + break_in_serdatr = 0; + break_delay = 0; + serdatr |= 0x100; serial_rx_irq(); } } #endif - if (data_in_serdatr) + if (data_in_serdatr) { serdatr_last_got++; - if (serial_period_hsyncs == 0) + } + if (serial_period_hsyncs == 0) { return; + } serial_period_hsync_counter++; if (serial_period_hsyncs == 1 || (serial_period_hsync_counter % (serial_period_hsyncs - 1)) == 0) { checkreceive_serial(); @@ -1026,6 +1070,18 @@ uae_u8 serial_readstatus(uae_u8 v, uae_u8 dir) if (ri) { status |= TIOCM_RI; } +#ifdef SERIAL_MAP + } else if (sermap_enabled) { + if (sermap_flags & 1) { + status |= TIOCM_DSR; + } + if (sermap_flags & 2) { + status |= TIOCM_CAR; + } + if (sermap_flags & 4) { + status |= TIOCM_CTS; + } +#endif } else if (currprefs.use_serial) { #ifdef SERIAL_PORT getserstat(&status); @@ -1164,6 +1220,32 @@ uae_u8 serial_writestatus (uae_u8 newstate, uae_u8 dir) } } +#ifdef SERIAL_MAP + if (sermap_data && sermap_enabled) { + uae_u32 flags = 0x80000000; + bool changed = false; + if (((oldserbits ^ newstate) & 0x80) && (dir & 0x80)) { + if (!(newstate & 0x80)) { + flags |= 1; // DSR + flags |= 2; // CD + } + changed = true; + } + if (!currprefs.serial_hwctsrts && (dir & 0x40)) { + if ((oldserbits ^ newstate) & 0x40) { + if (!(newstate & 0x40)) { + flags |= 4; // RTS + } + changed = true; + } + } + if (changed) { + shmem_serial_send(flags); + } + } +#endif + + oldserbits &= ~(0x80 | 0x40); newstate &= 0x80 | 0x40; oldserbits |= newstate; @@ -1203,7 +1285,7 @@ void serial_open (void) return; } } - if (alg_flag || currprefs.genlock_image >= 7 || cubo_enabled) { + if (alg_flag || currprefs.genlock_image >= 7 || cubo_enabled || sermap_enabled || rp_ismodem()) { serxdevice_enabled = true; } serdev = 1; @@ -1272,6 +1354,11 @@ void serial_exit (void) void serial_uartbreak (int v) { +#ifdef SERIAL_MAP + if (sermap_data && sermap_enabled) { + shmem_serial_send(0x40000000 | (v ? 0x20000 : 0x10000)); + } +#endif #ifdef SERIAL_PORT serialuartbreak (v); #endif -- 2.47.3