From cce54f4f885290834a7c1e8ea3e74959c6c5da32 Mon Sep 17 00:00:00 2001 From: Toni Wilen Date: Sun, 20 Dec 2015 13:03:38 +0200 Subject: [PATCH] Flush serial transmit buffer, intreq clear clears overrun bit. --- custom.cpp | 6 +++++ include/serial.h | 1 + od-win32/parser.cpp | 16 ++++++++--- od-win32/parser.h | 3 ++- od-win32/serial_win32.cpp | 57 +++++++++++++++++++++++++-------------- 5 files changed, 59 insertions(+), 24 deletions(-) diff --git a/custom.cpp b/custom.cpp index 00266f80..878d8642 100644 --- a/custom.cpp +++ b/custom.cpp @@ -5057,8 +5057,11 @@ void INTREQ_f (uae_u16 v) setclr (&intreq, v); send_intreq_do (v); } else { + uae_u16 old = intreq; setclr (&intreq, v); setclr (&intreq_internal, v); + if ((old & 0x0800) && !(intreq & 0x0800)) + serial_rbf_clear(); } } @@ -5071,6 +5074,9 @@ bool INTREQ_0 (uae_u16 v) uae_u16 old = intreq; setclr (&intreq, v); + if ((old & 0x0800) && !(intreq & 0x0800)) + serial_rbf_clear(); + if (int_recursive) { // don't add new event if this call came from send_intreq_do/rethink // and intreq didn't change. diff --git a/include/serial.h b/include/serial.h index 89e1412f..d603969d 100644 --- a/include/serial.h +++ b/include/serial.h @@ -25,6 +25,7 @@ extern void SERDAT (uae_u16 w); extern uae_u8 serial_writestatus (uae_u8, uae_u8); extern uae_u8 serial_readstatus (uae_u8); extern void serial_uartbreak (int); +extern void serial_rbf_clear (void); extern uae_u16 serdat; extern int doreadser, serstat; diff --git a/od-win32/parser.cpp b/od-win32/parser.cpp index f2824b86..1aeccaad 100644 --- a/od-win32/parser.cpp +++ b/od-win32/parser.cpp @@ -1091,17 +1091,27 @@ void closeser (void) static void outser (void) { - DWORD actual; - if (datainoutput > 0 && WaitForSingleObject (writeevent, 0) == WAIT_OBJECT_0 ) { + if (datainoutput <= 0) + return; + DWORD v = WaitForSingleObject (writeevent, 0); + if (v == WAIT_OBJECT_0) { + DWORD actual; memcpy (outputbufferout, outputbuffer, datainoutput); WriteFile (hCom, outputbufferout, datainoutput, &actual, &writeol); datainoutput = 0; } } +void writeser_flush(void) +{ + outser(); +} + void writeser (int c) { - //write_log(_T("writeser %d (buf=%d)\n"), c, datainoutput); +#if 0 + write_log(_T("writeser %04X (buf=%d)\n"), c, datainoutput); +#endif if (tcpserial) { if (tcp_is_connected ()) { char buf[1]; diff --git a/od-win32/parser.h b/od-win32/parser.h index 838a38ad..c9256d7c 100644 --- a/od-win32/parser.h +++ b/od-win32/parser.h @@ -14,7 +14,8 @@ void getserstat(int *status); void setserstat (int mask, int onoff); int readser (int *buffer); int readseravail (void); -void writeser (int c); +void writeser(int c); +void writeser_flush(void); int openser (const TCHAR *sername); void closeser (void); void doserout (void); diff --git a/od-win32/serial_win32.cpp b/od-win32/serial_win32.cpp index f0b20df4..d4165e69 100644 --- a/od-win32/serial_win32.cpp +++ b/od-win32/serial_win32.cpp @@ -27,7 +27,7 @@ #include "parser.h" #define SERIALLOGGING 0 -#define SERIALDEBUG 1 /* 0, 1, 2 3 */ +#define SERIALDEBUG 0 /* 0, 1, 2 3 */ #define SERIALHSDEBUG 0 #define SERIAL_HSYNC_BEFORE_OVERFLOW 200 @@ -246,7 +246,7 @@ void SERPER (uae_u16 w) #endif } -static TCHAR dochar (int v) +static TCHAR docharlog(int v) { v &= 0xff; if (v >= 32 && v < 127) @@ -256,6 +256,14 @@ static TCHAR dochar (int v) return '.'; } +static TCHAR dochar(int v) +{ + v &= 0xff; + if (v >= 32 && v < 127) + return v; + return '.'; +} + static void flushser(void) { while (readseravail() > 0) { @@ -374,7 +382,7 @@ static void serdatcopy(void); static void checksend(void) { - if (data_in_sershift != 1) + if (data_in_sershift != 1 && data_in_sershift != 2) return; #ifdef SERIAL_MAP @@ -388,29 +396,35 @@ static void checksend(void) #endif #ifdef SERIAL_PORT if (ninebit) { - if (!checkserwrite(2)) + if (!checkserwrite(2)) { + data_in_sershift = 2; return; + } writeser(((serdatshift >> 8) & 1) | 0xa8); writeser(serdatshift_masked); } else { if (currprefs.serial_crlf) { if (serdatshift_masked == 10 && serial_send_previous != 13) { - if (!checkserwrite(2)) + if (!checkserwrite(2)) { + data_in_sershift = 2; return; + } writeser(13); } } - if (!checkserwrite(1)) + if (!checkserwrite(1)) { + data_in_sershift = 2; return; + } writeser(serdatshift_masked); serial_send_previous = serdatshift_masked; } #endif - if (serial_period_hsyncs <= 1) { + if (serial_period_hsyncs <= 1 || data_in_sershift == 2) { data_in_sershift = 0; serdatcopy(); } else { - data_in_sershift = 2; + data_in_sershift = 3; } #if SERIALDEBUG > 2 write_log(_T("SERIAL: send %04X (%c)\n"), serdatshift, dochar(serdatshift)); @@ -419,8 +433,9 @@ static void checksend(void) static bool checkshiftempty(void) { + writeser_flush(); checksend(); - if (data_in_sershift == 2) { + if (data_in_sershift == 3) { data_in_sershift = 0; serdatcopy(); return true; @@ -433,7 +448,7 @@ static void sersend_ce(uae_u32 v) if (checkshiftempty()) { lastbitcycle = get_cycles() + ((serper & 0x7fff) + 1) * CYCLE_UNIT; lastbitcycle_active_hsyncs = ((serper & 0x7fff) + 1) / maxhpos + 2; - } else if (data_in_sershift == 1) { + } else if (data_in_sershift == 1 || data_in_sershift == 2) { event2_newevent_x(-1, maxhpos, 0, sersend_ce); } } @@ -455,14 +470,12 @@ static void serdatcopy(void) if (seriallog) { gotlogwrite = true; - write_log(_T("%c"), dochar(serdatshift_masked)); + write_log(_T("%c"), docharlog(serdatshift_masked)); } if (serper == 372) { if (enforcermode & 2) { - console_out_f(_T("%c"), dochar(serdatshift_masked)); - if (serdatshift_masked == 10) - console_out(_T("\n")); + console_out_f(_T("%c"), docharlog(serdatshift_masked)); } } @@ -538,6 +551,10 @@ void serial_hsynchandler (void) void SERDAT (uae_u16 w) { +#if SERIALDEBUG > 2 + write_log(_T("SERIAL: SERDAT write 0x%04x (%c) PC=%x\n"), w, dochar(w), M68K_GETPC); +#endif + serdatcopy(); serdat = w; @@ -557,10 +574,6 @@ void SERDAT (uae_u16 w) data_in_serdat = 1; serdatcopy(); - -#if SERIALDEBUG > 2 - write_log (_T("SERIAL: wrote 0x%04x (%c) PC=%x\n"), w, dochar (w), M68K_GETPC); -#endif } uae_u16 SERDATR (void) @@ -577,16 +590,20 @@ uae_u16 SERDATR (void) #if SERIALDEBUG > 2 write_log (_T("SERIAL: read 0x%04x (%c) %x\n"), serdatr, dochar (serdatr), M68K_GETPC); #endif - ovrun = 0; data_in_serdatr = 0; return serdatr; } +void serial_rbf_clear(void) +{ + ovrun = 0; +} + void serial_check_irq (void) { // Data in receive buffer if (data_in_serdatr) - INTREQ(0x8000 | 0x0800); + INTREQ_0(0x8000 | 0x0800); } void serial_dtr_on (void) -- 2.47.3