]> git.unchartedbackwaters.co.uk Git - francis/winuae.git/commitdiff
inter-process serial port stability fix, status signal and break support.
authorToni Wilen <twilen@winuae.net>
Sun, 30 Apr 2023 18:10:59 +0000 (21:10 +0300)
committerToni Wilen <twilen@winuae.net>
Sun, 30 Apr 2023 18:10:59 +0000 (21:10 +0300)
od-win32/serial_win32.cpp

index 448ea8d780e0c291f435c2417849e8a7abf99158..bbb0e18eef75fafc1b353033914c4bb93c877f2f 100644 (file)
@@ -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