Index: man/de/srcpd.conf.5
===================================================================
--- man/de/srcpd.conf.5	(.../patch_14_bw-cumulative_patch_11-13)	(Revision 1921)
+++ man/de/srcpd.conf.5	(.../patch_15_bw-ACKdetection)	(Revision 1921)
@@ -551,6 +551,27 @@ was bedeutet, dass Prpgrammierbefehle st
 weitergeleitet werden.
 .\"
 .TP
+scanACK_delay (nur NMRA Programmiergleis)
+pause im microseconds before scanACK function. Default: 9000
+.\"
+.TP
+handleACK_delay (nur NMRA Programmiergleis)
+pause im microseconds before handleACK function. Default: 10000
+.\"
+.TP
+ACK_samplingtime (nur NMRA Programmiergleis)
+time in microseconds between two samplings for ACK detection. Default: 200
+.\"
+.TP
+ACK_debouncer (nur NMRA Programmiergleis)
+number of samples before assessing ACK=LOW as valid. Default: 4
+.\"
+.PP
+Wenn mindestens einer der Parameter scanACK_delay, handleACK_delay,
+ACK_samplingtime oder ACK_debouncer gesetzt ist, findet eine ausführlichere
+Abtastung des RI Signals statt.
+.\"
+.TP
 rpi_dtr
 .TQ
 rpi_rts
Index: man/srcpd.conf.5
===================================================================
--- man/srcpd.conf.5	(.../patch_14_bw-cumulative_patch_11-13)	(Revision 1921)
+++ man/srcpd.conf.5	(.../patch_15_bw-ACKdetection)	(Revision 1921)
@@ -458,6 +458,27 @@ input values are \fByes\fR or \fBno\fR.
 i.e. all program track commands will be executed by default.
 .\"
 .TP
+scanACK_delay (NMRA programming track only)
+pause im microseconds before scanACK function. Default: 9000
+.\"
+.TP
+handleACK_delay (NMRA programming track only)
+pause im microseconds before handleACK function. Default: 10000
+.\"
+.TP
+ACK_samplingtime (NMRA programming track only)
+time in microseconds between two samplings for ACK detection. Default: 200
+.\"
+.TP
+ACK_debouncer (NMRA programming track only)
+number of samples before assessing ACK=LOW as valid. Default: 4
+.\"
+.PP
+If at least one of the parameters scanACK_delay, handleACK_delay,
+ACK_samplingtime or ACK_debouncer is set, a more elaborated sampling
+of the RI control line is done.
+.\"
+.TP
 rpi_dtr
 .TQ
 rpi_rts
Index: src/ddl.c
===================================================================
--- src/ddl.c	(.../patch_14_bw-cumulative_patch_11-13)	(Revision 1921)
+++ src/ddl.c	(.../patch_15_bw-ACKdetection)	(Revision 1921)
@@ -18,8 +18,6 @@
 /* | gpl-license@vogt-it.com so we can mail you a copy immediately.       | */
 /* +----------------------------------------------------------------------+ */
 
-/* 2021 changes by Bernd Wagner to support custom baudrates for NMRA DCC */
-
 /***************************************************************/
 /* erddcd - Electric Railroad Direct Digital Command Daemon    */
 /*    generates without any other hardware digital commands    */
@@ -56,6 +54,8 @@
 
 /* 18.03.2021 Bernd Wagner
     adaptions to include Raspberry Pi support */
+/* 2019-2021 changes by Bernd Wagner to support ACK detection */
+/* 2021 changes by Bernd Wagner to support custom baudrates for NMRA DCC */
 
 #include <sys/utsname.h>
 #include <stdbool.h>
@@ -811,7 +811,7 @@ static void waitUARTempty_COMMON(bus_t b
 #endif
         if (result == -1) {
             syslog_bus(busnumber, DBG_ERROR,
-                       "ioctl() failed: %s (errno = %d)\n",
+                       "ioctl() waitUARTempty_COMMON failed: %s (errno = %d)\n",
                        strerror(errno), errno);
         }
     } while (!value);
@@ -831,7 +831,7 @@ static void waitUARTempty_COMMON_USLEEPP
 #endif
         if (result == -1) {
             syslog_bus(busnumber, DBG_ERROR,
-                       "ioctl() failed: %s (errno = %d)\n",
+                       "ioctl() waitUARTempty_COMMON_USLEEPPATCH failed: %s (errno = %d)\n",
                        strerror(errno), errno);
         }
         if (usleep(__DDL->WAITUART_USLEEP_USEC) == -1) {
@@ -856,7 +856,7 @@ static void waitUARTempty_CLEANNMRADCC(b
     result = ioctl(buses[busnumber].device.file.fd, TIOCOUTQ, &outbytes);
     if (result == -1) {
         syslog_bus(busnumber, DBG_ERROR,
-                   "ioctl() failed: %s (errno = %d)\n",
+                   "ioctl() waitUARTempty_CLEANNMRADCC failed: %s (errno = %d)\n",
                    strerror(errno), errno);
     }
 
@@ -886,7 +886,7 @@ static int checkRingIndicator(bus_t busn
     }
     else {
         syslog_bus(busnumber, DBG_ERROR,
-                   "ioctl() failed: %s (errno = %d). Power on tracks stopped!",
+                   "ioctl() checkRingIndicator failed: %s (errno = %d). Power on tracks stopped!",
                    strerror(errno), errno);
         return 1;
     }
@@ -923,7 +923,7 @@ static int checkShortcut(bus_t busnumber
     }
     else {
         syslog_bus(busnumber, DBG_INFO,
-                   "ioctl() failed: %s (errno = %d). Power on tracks stopped!",
+                   "ioctl() __checkShortcut failed: %s (errno = %d). Power on tracks stopped!",
                    strerror(errno), errno);
         return 1;
     }
@@ -1139,7 +1139,7 @@ static void set_SerialLine(bus_t busnumb
     result = IOCTL(buses[busnumber].device.file.fd, TIOCMGET, &arg);
     if (result == -1) {
         syslog_bus(busnumber, DBG_ERROR,
-                   "ioctl() failed: %s (errno = %d). "
+                   "ioctl() set_SerialLine TIOCMGET failed: %s (errno = %d). "
                    "Serial line not set! (%d: %d)",
                    strerror(errno), errno, line, mode);
     }
@@ -1179,7 +1179,7 @@ static void set_SerialLine(bus_t busnumb
         result = IOCTL(buses[busnumber].device.file.fd, TIOCMSET, &arg);
         if (result == -1) {
             syslog_bus(busnumber, DBG_FATAL,
-                       "ioctl() failed: %s (errno = %d).",
+                       "ioctl() set_SerialLine TIOCMSET failed: %s (errno = %d).",
                        strerror(result), result);
             /*What to do now */
         }
@@ -1644,6 +1644,11 @@ int readconfig_DDL(xmlDocPtr doc, xmlNod
     __DDL->WAITUART_USLEEP_USEC = 100;  /* usecs for usleep patch      */
     __DDL->NMRA_GA_OFFSET = 0;  /* offset for ga base address 0 or 1  */
     __DDL->PROGRAM_TRACK = 1;   /* 0: suppress SM commands to PT address */
+    __DDL->USE_SCANACK2 = false; /* use alternative scanACK */
+    __DDL->SCANACK_DELAY = 9000 ; /* pause before scanACK usecs */
+    __DDL->HANDLEACK_DELAY = 10000; /* pause before handleACK usecs */
+    __DDL->ACK_SAMPLINGTIME = 200;  /* time between two samplings for ACK detection usecs */
+    __DDL->ACK_DEBOUNCER = 4;		/* number of samples to assess ACK=LOW as valid */
 
     __DDL->SERIAL_DEVICE_MODE = SDM_NOTINITIALIZED;
 
@@ -1811,7 +1816,41 @@ int readconfig_DDL(xmlDocPtr doc, xmlNod
                 xmlFree(txt);
             }
         }
+        else if (xmlStrcmp(child->name, BAD_CAST "scanACK_delay") == 0) {
+            txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
+            if (txt != NULL) {
+                __DDL->SCANACK_DELAY = atoi((char *) txt);
+                __DDL->USE_SCANACK2 = true;
+                xmlFree(txt);
+            }
+        }
 
+        else if (xmlStrcmp(child->name, BAD_CAST "handleACK_delay") == 0) {
+            txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
+            if (txt != NULL) {
+                __DDL->HANDLEACK_DELAY = atoi((char *) txt);
+                __DDL->USE_SCANACK2 = true;
+                xmlFree(txt);
+            }
+        }
+
+        else if (xmlStrcmp(child->name, BAD_CAST "ACK_samplingtime") == 0) {
+            txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
+            if (txt != NULL) {
+                __DDL->ACK_SAMPLINGTIME = atoi((char *) txt);
+                __DDL->USE_SCANACK2 = true;
+                xmlFree(txt);
+            }
+        }
+
+        else if (xmlStrcmp(child->name, BAD_CAST "ACK_debouncer") == 0) {
+            txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
+            if (txt != NULL) {
+                __DDL->ACK_DEBOUNCER = atoi((char *) txt);
+                __DDL->USE_SCANACK2 = true;
+                xmlFree(txt);
+            }
+        }
 #ifdef RASPBERRYPI
         else if ((i=check_rpi_opts(child))<=NO_OF_CONTROLLINES) {
             txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
Index: src/ddl.h
===================================================================
--- src/ddl.h	(.../patch_14_bw-cumulative_patch_11-13)	(Revision 1921)
+++ src/ddl.h	(.../patch_15_bw-ACKdetection)	(Revision 1921)
@@ -107,6 +107,12 @@ typedef struct _DDL_DATA {
     int NMRA_GA_OFFSET;         /* offset for ga base address 0/1*/
 
     int PROGRAM_TRACK;          /* 0: suppress SM commands to PT address */
+    bool USE_SCANACK2;          /* use alternative scanACK */
+    int SCANACK_DELAY;          /* pause before scanACK usecs */
+    int HANDLEACK_DELAY;        /* pause before handleACK usecs */
+    int ACK_SAMPLINGTIME;       /* time between two samplings for ACK detection usecs */
+    int ACK_DEBOUNCER;			/* number of samples to assess ACK=LOW as valid */
+
     struct termios maerklin_dev_termios;
     struct termios nmra_dev_termios;
 
Index: src/ddl_nmra.c
===================================================================
--- src/ddl_nmra.c	(.../patch_14_bw-cumulative_patch_11-13)	(Revision 1921)
+++ src/ddl_nmra.c	(.../patch_15_bw-ACKdetection)	(Revision 1921)
@@ -263,13 +263,17 @@
 #define hHHl        0xF5
 #define hHHHl       0xd5
 
+#define __DDL ((DDL_DATA*)buses[busnumber].driverdata)
+
 #include <time.h>
 
+#include "config.h"
+#include "ddl_raspi.h"
 #include "ddl.h"
 #include "ddl_nmra.h"
 #include "syslogmessage.h"
-#include "ddl_raspi.h"
 
+enum {HANDLEACK, WAITUARTEMPTY_SCANACK};
 
 typedef struct {
     char *pattern;
@@ -1316,7 +1320,7 @@ static int scanACK(bus_t busnumber)
     result = IOCTL(buses[busnumber].device.file.fd, TIOCMGET, &arg);
     if (result == -1) {
         syslog_bus(busnumber, DBG_ERROR,
-                   "ioctl() failed: %s (errno = %d)\n",
+                     "ioctl() scanACK failed: %s (errno = %d)\n",
                    strerror(errno), errno);
     }
 
@@ -1325,6 +1329,91 @@ static int scanACK(bus_t busnumber)
     return 0;
 }
 
+
+static int scanACK2(bus_t busnumber, int caller)
+/* more elaborated scanACK used when timing parameters are given in the conf-file */
+{
+    int result, arg;
+    int delay, edgetime, sleeptime, limit, debouncer, loglevel;
+
+    delay = 0;
+    edgetime = 0;
+    sleeptime = __DDL->ACK_SAMPLINGTIME;
+    debouncer = 0;
+
+    if (caller == WAITUARTEMPTY_SCANACK)
+    {
+
+        result = 0;
+
+        limit = __DDL->SCANACK_DELAY / sleeptime;
+
+        do
+        {
+            if (usleep(sleeptime) == -1)
+            {
+                syslog_bus(busnumber, DBG_ERROR,
+                           "usleep() in scanACK failed: %s (errno = %d)\n",
+                           strerror(errno), errno);
+            }
+            delay++;
+            if (scanACK(busnumber) && (edgetime == 0))
+            {
+                debouncer++;
+                if (debouncer > __DDL->ACK_DEBOUNCER)
+                {
+                    edgetime = delay - (__DDL->ACK_DEBOUNCER);
+                    result = 1;
+                }
+            }
+            else
+                debouncer = 0;
+        } while ((delay < limit) && (edgetime == 0));
+    }
+
+    else
+    {
+        limit = __DDL->HANDLEACK_DELAY / sleeptime;
+        do
+        {
+            if (usleep(sleeptime) == -1)
+            {
+                syslog_bus(busnumber, DBG_ERROR,
+                           "usleep() in scanACK failed: %s (errno = %d)\n",
+                           strerror(errno), errno);
+            }
+            delay++;
+            if (!scanACK(busnumber) && (edgetime == 0))
+            {
+                debouncer++;
+                if (debouncer > 5)
+                    edgetime = delay - 5;
+            }
+            else
+                debouncer = 0;
+        } while ((delay < limit) && (edgetime == 0));
+        result = scanACK(busnumber);
+    }
+
+    if (result == 1)
+    {
+        if (edgetime == 0)
+        {
+            loglevel = DBG_WARN; // no edge detected
+            syslog_bus(busnumber, DBG_WARN, "scanACK Ring Indicator no edge detected in wait loop");
+        }
+        else
+            loglevel = DBG_INFO;
+    }
+    else
+        loglevel = (caller == WAITUARTEMPTY_SCANACK ? DBG_DEBUG : DBG_INFO);
+
+    syslog_bus(busnumber, loglevel,
+               "scanACK Ring Indicator result= %d, edge_time=%d, wait_time==%d, caller=%d\n", result, edgetime * sleeptime, delay * sleeptime, caller);
+
+    return result;
+}
+
 /**
   Wait for the UART to write the packetstream
   check in the meantime if an ack is set
@@ -1338,8 +1427,14 @@ static int waitUARTempty_scanACK(bus_t b
     int ack = 0;
     clock_t start = clock();
     do {                        /* wait until UART is empty */
+        if ( __DDL->USE_SCANACK2 ) {
+            if (scanACK2(busnumber, WAITUARTEMPTY_SCANACK))
+                ack = 1;            /* scan ACK */
+        }
+        else {
         if (scanACK(busnumber))
             ack = 1;            /* scan ACK */
+        }
         /* prevent endless loop in case somone turned the power on */
         if (buses[busnumber].power_state == 1) {
             clock_t now = clock();
@@ -1358,7 +1453,7 @@ static int waitUARTempty_scanACK(bus_t b
         else {
 #if linux
             result =
-                ioctl(buses[busnumber].device.file.fd, TIOCSERGETLSR,
+                ioctl(buses[busnumber].device.file.fd, TIOCSERGETLSR, /* called to retrieve the line status register (LSR) value of your tty device. */
                       &value);
 #else
             result =
@@ -1367,7 +1462,7 @@ static int waitUARTempty_scanACK(bus_t b
         }
         if (result == -1) {
             syslog_bus(busnumber, DBG_ERROR,
-                       "ioctl() failed: %s (errno = %d)\n",
+                       "ioctl() waitUARTempty_scanACK failed: %s (errno = %d)\n",
                        strerror(errno), errno);
         }
     } while (!value);
@@ -1375,6 +1470,10 @@ static int waitUARTempty_scanACK(bus_t b
     /* if power is on do not turn it off */
     if (!buses[busnumber].power_state)
         tcflow(buses[busnumber].device.file.fd, TCOOFF);
+
+    syslog_bus(busnumber, DBG_INFO,
+               "function waitUARTempty_scanACK  called with result %d\n", ack);
+
     return ack;
 }
 
@@ -1387,7 +1486,26 @@ static int waitUARTempty_scanACK(bus_t b
 */
 static int handleACK(bus_t busnumber, int ack)
 {
-    if (usleep(5000) == -1) {
+    if (__DDL->USE_SCANACK2)
+    {
+        if ((scanACK2(busnumber, HANDLEACK) == 1) && (ack == 1))
+        {
+            syslog_bus(busnumber, DBG_INFO,
+                       "function handleACK  called with ack=1 and result 0\n");
+            return 0;
+        }
+        /* ack supported ==> send to client */
+        else
+        {
+            syslog_bus(busnumber, DBG_INFO,
+                       "function handleACK  called with result ack=%d\n", ack);
+            return ack;
+        }
+    }
+    else
+    {
+        if (usleep(5000) == -1)
+        {
         syslog_bus(busnumber, DBG_ERROR,
                    "usleep() failed: %s (errno = %d)\n",
                    strerror(errno), errno);
@@ -1400,6 +1518,7 @@ static int handleACK(bus_t busnumber, in
     else
         return ack;
 }
+}
 
 /**
   Generate command stream to access a physical register
Index: src/ddl_raspi.c
===================================================================
Index: .
===================================================================
--- .	(.../patch_14_bw-cumulative_patch_11-13)	(Revision 1921)
+++ .	(.../patch_15_bw-ACKdetection)	(Revision 1921)

Eigenschaftsänderungen: .
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,1 ##
   Zusammengeführt /tags/patch_14_bw-cumulative_patch_11-13:r1915
