Index: README.raspberrypi
===================================================================
--- README.raspberrypi	(.../tags/RELEASE_2_1_5)	(nicht existent)
+++ README.raspberrypi	(.../branches/bw-raspidefs)	(Revision 1906)
@@ -0,0 +1,62 @@
+Author: Bernd Wagner
+Datum: 22.03.2021
+Version: SRCP 2.1.5
+Licence: GPL v2 for the whole package 
+
+The DDL driver of srcpd uses the transmit line of a RS232 interface of a PC to
+output the digital signal for model train control.
+
+Besides this transmit (and a receive) line, a RS232 has several control lines
+e.g. for handshaking during communication and these lines may be needed for
+communication with a booster.
+
+Raspberry Pi has UART interface(s) (i.e. transmit and receive), but only 
+limited control lines (CTS/RTS, but not DTR, DSR or RI). On a Raspberry Pi, 
+these control lines can be emulated by programming GPIOs.
+
+The files src/ddl_raspi.[hc] contain this programming for the control lines
+DTR, DSR, RI, RTS and CTS. The switch between PC specific functions and
+Raspberry Pi specific functions is done by the macro IOCTL defined in src/ddl.h.
+The activation of of the Raspberry Pi specific parts is done by the preprocessor
+variable RASPBERRYPI, which is set during ./configure when ./configure detects
+to be processed on a Raspberry Pi.
+
+For the GPIO programming the bcm2835 library from
+http://www.airspayce.com/mikem/bcm2835/ is used, which must be installed on the
+Raspberry Pi (and is requested by ./configure). This library uses the GPIO numbers
+of the BCM2835 SoC (_not_ the Raspberry's pin numbers). See
+https://elinux.org/RPi_BCM2835_GPIOs for a list.
+
+The configuration of the GPIO numbers used for the emulation of RS232 control
+lines is done in srcpd.conf - see manual page for a description.
+In my test environment, I used the following GPIO configuration
+on a Raspberry Pi 1:
+<rpi_rts>27</rpi_rts>
+<rpi_cts>18</rpi_cts>
+<rpi_dsr>17</rpi_dsr>
+<rpi_ri>22</rpi_ri>
+<rpi_dtr>4</rpi_dtr>
+Look at your Raspberry Pi's description to choose which GPIOs are free for 
+use in your case, and check at your booster which RS232 control lines are really used.
+DTR is a hot candidate to switch train power on and off.
+Look at the srcpd.conf manual page for information how RI and DSR should be
+used by srcpd if activated in the configuration and if the booster provides them.
+Furthermore, RI is used by srcpd for ACK detection on a NMRA programming track.
+
+Please respect that different electrical conditions may apply for Raspbery Pi
+(3,3 V) and booster (RS232 uses +- 12V). An example for interface hardware
+for an individual setup can be found at 
+http://siggsoftware.ch/wordpress/wp-content/uploads/2016/11/booster.pdf
+
+In case inversion of logics (invert HIGH and LOW) is needed, this can be done
+by hardware or by configuration in srcpd.conf (or one can be used to compensate
+the other).
+
+Furthermore optocouplers may be needed for potential separation between
+Raspberry PI and model train, particularly if there are other interfaces
+between them like i2c.
+
+This work is based on the srcpd fork to be found on
+http://siggsoftware.ch/wordpress/srcpd-mit-mfx-und-anderen-erweiterungen/
+but encapsulated to minimize changes in src/ddl.[ch]  and modified to
+allow flexible configuration in srcpd.conf.
Index: configure.ac
===================================================================
--- configure.ac	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ configure.ac	(.../branches/bw-raspidefs)	(Revision 1906)
@@ -177,6 +177,16 @@ case $host in
     AC_MSG_WARN(System $host not known.)
     ;;
 esac
+case $host in
+  arm*-*-linux*)
+    if [grep 'Raspberry' /proc/device-tree/model >/dev/null 2>&1]; then
+      AC_DEFINE([RASPBERRYPI], [1], [Raspberry PI found])
+      AC_CHECK_LIB(bcm2835, bcm2835_gpio_write, , AC_MSG_ERROR(lib bcm2835 is missing))
+    fi
+    ;;
+  *)
+    ;;
+esac
 
 
 dnl Checks for header files.
@@ -340,8 +350,8 @@ if test "$with_DCCAR"     != "yes"; then
 
 echo
 if test $NUM_MODULES == 0; then
-    echo 'Warning: No device module configured; srcpd will not run propperly!'
+    echo 'Warning: No device module configured; srcpd will not run properly!'
 else
     echo "Run 'make' to continue."
 fi
-echo
+echo $host
Index: man/de/srcpd.conf.5
===================================================================
--- man/de/srcpd.conf.5	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ man/de/srcpd.conf.5	(.../branches/bw-raspidefs)	(Revision 1906)
@@ -536,6 +536,36 @@ was bedeutet, dass Prpgrammierbefehle st
 weitergeleitet werden.
 .\"
 .TP
+rpi_dtr
+.TQ
+rpi_rts
+.TQ
+rpi_cts
+.TQ
+rpi_dsr
+.TQ
+rpi_ri
+.TQ
+.I
+(nur Raspberry Pi)
+Diese Parameter ermöglichen die Verwendung der GPIOs des Raspberry Pi für die
+RS232 Steuerleitungen wie in README.raspberrypi beschrieben (logisch - 
+Hardware-Anpassung erforderlich).
+Der angegebene Paramater wird als GPIO Nummer für die im Tag angegebene
+Steuerleitung verwendet, z.B.
+.br
+<rpi_dtr>4</rpi_dtr>
+.br
+gibt an, dass GPIO 4 für die DTR-Leitung verwendet werden soll (High = active).
+Addition von 1000 bzw. 2000 zum Parameter gibt an, dass der interne pulldown
+bzw. Pullup-Widerstand des GPIO aktiviert werden soll (für Eingänge).
+Ein Minuszeichen stellt auf inverse Logik um (Low = aktiv). So bedeutet
+.br
+<rpi_ri>-2022</rpi_ri>
+.br
+dass GPIO 22 für RI verwendet werden soll mit internem Pullup und inverser Logik.
+.\"
+.TP
 Beispiel Märklin/Motorola
 .nf
 <bus>
Index: man/srcpd.conf.5
===================================================================
--- man/srcpd.conf.5	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ man/srcpd.conf.5	(.../branches/bw-raspidefs)	(Revision 1906)
@@ -443,6 +443,35 @@ input values are \fByes\fR or \fBno\fR.
 i.e. all program track commands will be executed by default.
 .\"
 .TP
+rpi_dtr
+.TQ
+rpi_rts
+.TQ
+rpi_cts
+.TQ
+rpi_dsr
+.TQ
+rpi_ri
+.TQ
+.I
+(Raspberry Pi only)
+These parameters enable to use Raspberry Pi's GPIOs as RS232 control lines,
+as indicated in README.raspberrypi (logically - hardware adaption needed).
+The parameter given is taken as GPIO number used for the control line indicated
+by the tag, e.g.
+.br
+<rpi_dtr>4</rpi_dtr>
+.br
+indicates that GPIO 4 is to be taken for the DTR control line (High = active).
+Adding 1000 or 2000 to the parameter indicates activation of the GPIOs internal
+pulldown or pullup resistor respectively (for inputs). A minus indicates to use
+inverse logics (Low = active). So
+.br
+<rpi_ri>-2022</rpi_ri>
+.br
+means that GPIO 22 shall be used for RI with internal pullup and inverse logics.
+.\"
+.TP
 Example Maerklin/Motorola
 .nf
 <bus>
Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ src/Makefile.am	(.../branches/bw-raspidefs)	(Revision 1906)
@@ -35,7 +35,8 @@ if USE_DDL
 srcpd_SOURCES += \
 	ddl.c ddl.h \
 	ddl_maerklin.c ddl_maerklin.h \
-	ddl_nmra.c ddl_nmra.h
+	ddl_nmra.c ddl_nmra.h \
+	ddl_raspi.c ddl_raspi.h
 endif
 
 if USE_DDLS88
Index: src/ddl.c
===================================================================
--- src/ddl.c	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ src/ddl.c	(.../branches/bw-raspidefs)	(Revision 1906)
@@ -52,6 +52,9 @@
 /* Berthold Benning: usleep patch for SuSE kernels             */
 /***************************************************************/
 
+/* 18.03.2021 Bernd Wagner
+    adaptions to include Raspberry Pi support */
+
 #include <sys/utsname.h>
 #include <stdbool.h>
 
@@ -59,7 +62,7 @@
 #include "ddl.h"
 #include "ddl_maerklin.h"
 #include "ddl_nmra.h"
-#include "io.h"
+/* #include "io.h" */
 #include "srcp-error.h"
 #include "srcp-fb.h"
 #include "srcp-ga.h"
@@ -69,6 +72,7 @@
 #include "srcp-power.h"
 #include "srcp-server.h"
 #include "syslogmessage.h"
+#include "ddl_raspi.h"
 
 #define __DDL ((DDL_DATA*)buses[busnumber].driverdata)
 #define __DDLt ((DDL_DATA*)buses[btd->bus].driverdata)
@@ -760,7 +764,7 @@ static int checkRingIndicator(bus_t busn
 {
     int result, arg;
 
-    result = ioctl(buses[busnumber].device.file.fd, TIOCMGET, &arg);
+    result = IOCTL(buses[busnumber].device.file.fd, TIOCMGET, &arg);
     if (result >= 0) {
         if (arg & TIOCM_RI) {
             syslog_bus(busnumber, DBG_INFO,
@@ -783,7 +787,7 @@ static int checkShortcut(bus_t busnumber
     time_t short_now = 0;
     struct timeval tv_shortcut = { 0, 0 };
 
-    result = ioctl(buses[busnumber].device.file.fd, TIOCMGET, &arg);
+    result = IOCTL(buses[busnumber].device.file.fd, TIOCMGET, &arg);
     if (result >= 0) {
         if (((arg & TIOCM_DSR) && (!__DDL->DSR_INVERSE))
             || ((~arg & TIOCM_DSR) && (__DDL->DSR_INVERSE))) {
@@ -1021,7 +1025,7 @@ static void set_SerialLine(bus_t busnumb
 {
     int result, arg;
 
-    result = ioctl(buses[busnumber].device.file.fd, TIOCMGET, &arg);
+    result = IOCTL(buses[busnumber].device.file.fd, TIOCMGET, &arg);
     if (result == -1) {
         syslog_bus(busnumber, DBG_ERROR,
                    "ioctl() failed: %s (errno = %d). "
@@ -1061,7 +1065,7 @@ static void set_SerialLine(bus_t busnumb
                     arg |= TIOCM_CTS;
                 break;
         }
-        result = ioctl(buses[busnumber].device.file.fd, TIOCMSET, &arg);
+        result = IOCTL(buses[busnumber].device.file.fd, TIOCMSET, &arg);
         if (result == -1) {
             syslog_bus(busnumber, DBG_FATAL,
                        "ioctl() failed: %s (errno = %d).",
@@ -1531,6 +1535,13 @@ int readconfig_DDL(xmlDocPtr doc, xmlNod
 
     __DDL->SERIAL_DEVICE_MODE = SDM_NOTINITIALIZED;
 
+#ifdef RASPBERRYPI
+    for (int i=0; i < NO_OF_CONTROLLINES; i++) {
+        __DDL->rpi_GPIO_used[i] = false; 
+    }
+    int i;
+#endif
+
     xmlNodePtr child = node->children;
     xmlChar *txt = NULL;
 
@@ -1676,6 +1687,14 @@ int readconfig_DDL(xmlDocPtr doc, xmlNod
                 xmlFree(txt);
             }
         }
+
+#ifdef RASPBERRYPI
+        else if ((i=check_rpi_opts(child))<=NO_OF_CONTROLLINES) {
+            txt = xmlNodeListGetString(doc, child->xmlChildrenNode, 1);
+            interpret_rpi_parameter(i, txt, busnumber, __DDL);
+            xmlFree(txt);
+        }
+#endif
         else
             syslog_bus(busnumber, DBG_WARN,
                        "WARNING, unknown tag found: \"%s\"!\n",
@@ -1719,6 +1738,10 @@ int init_bus_DDL(bus_t busnumber)
 
     buses[busnumber].device.file.fd = init_lineDDL(busnumber);
 
+#ifdef RASPBERRYPI
+    init_raspi(busnumber, __DDL);
+#endif
+
     __DDL->short_detected = 0;
 
     __DDL->queue_initialized = false;
Index: src/ddl.h
===================================================================
--- src/ddl.h	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ src/ddl.h	(.../branches/bw-raspidefs)	(Revision 1906)
@@ -27,6 +27,13 @@
 #include <linux/serial.h>
 #endif
 
+#include "config.h"
+#ifdef RASPBERRYPI
+#define IOCTL(a, b, c) ioctl_raspi(a, b, c, busnumber, (DDL_DATA*)buses[busnumber].driverdata)
+#else
+#define IOCTL ioctl
+#endif
+
 #include <libxml/tree.h>        /*xmlDocPtr, xmlNodePtr */
 
 #include "config-srcpd.h"
@@ -102,6 +109,14 @@ typedef struct _DDL_DATA {
     struct serial_struct *serinfo_marklin;
     struct serial_struct *serinfo_nmradcc;
 #endif
+#ifdef RASPBERRYPI
+#define NO_OF_CONTROLLINES 5  /* number of supported RS232 control lines, length of rpi_controllines[] */
+    int rpi_GPIO[NO_OF_CONTROLLINES];
+    bool rpi_GPIO_inverted[NO_OF_CONTROLLINES];
+    bool rpi_GPIO_pullup[NO_OF_CONTROLLINES];
+    bool rpi_GPIO_pulldown[NO_OF_CONTROLLINES];
+    bool rpi_GPIO_used[NO_OF_CONTROLLINES];
+#endif
     pthread_mutex_t queue_mutex;        /* mutex to synchronize queue inserts */
     int queue_initialized;
     int queue_out, queue_in;
Index: src/ddl_nmra.c
===================================================================
--- src/ddl_nmra.c	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ src/ddl_nmra.c	(.../branches/bw-raspidefs)	(Revision 1906)
@@ -268,6 +268,7 @@
 #include "ddl.h"
 #include "ddl_nmra.h"
 #include "syslogmessage.h"
+#include "ddl_raspi.h"
 
 
 typedef struct {
@@ -1312,7 +1313,7 @@ static void sm_init(bus_t busnumber)
 static int scanACK(bus_t busnumber)
 {
     int result, arg;
-    result = ioctl(buses[busnumber].device.file.fd, TIOCMGET, &arg);
+    result = IOCTL(buses[busnumber].device.file.fd, TIOCMGET, &arg);
     if (result == -1) {
         syslog_bus(busnumber, DBG_ERROR,
                    "ioctl() failed: %s (errno = %d)\n",
Index: src/ddl_raspi.c
===================================================================
--- src/ddl_raspi.c	(.../tags/RELEASE_2_1_5)	(nicht existent)
+++ src/ddl_raspi.c	(.../branches/bw-raspidefs)	(Revision 1906)
@@ -0,0 +1,124 @@
+/*
+* This software is published under the terms of the GNU General Public
+* License, Version 2, 1991. (c) Bernd Wagner 18.03.2021.
+*/
+/* for further information see README.raspberrypi */
+
+#include <stdlib.h>
+#include <sys/ioctl.h>
+
+#include "ddl_raspi.h"
+
+#ifdef RASPBERRYPI
+
+#include "syslogmessage.h"
+
+const char rpi_controllines[NO_OF_CONTROLLINES][8] = {"rpi_dtr", "rpi_rts", "rpi_cts", "rpi_dsr", "rpi_ri"};
+const unsigned int TIOCM_bit[NO_OF_CONTROLLINES] =   {TIOCM_DTR, TIOCM_RTS, TIOCM_CTS, TIOCM_DSR, TIOCM_RI};
+const bool controllines_isoutput[NO_OF_CONTROLLINES] = {true,    true,      false,     false,     false}; /* direction of RS232 control lines */
+
+int ioctl_raspi (int fd, unsigned long int request, int* argptr, bus_t busnumber, DDL_DATA* ddlptr) 
+{
+    
+    switch (request) {
+
+        case TIOCMGET:
+
+            *argptr = 0;
+            for (int i=0; i<NO_OF_CONTROLLINES; i++ ){
+                *argptr |= (ddlptr->rpi_GPIO_used[i] ? 
+                    (ddlptr->rpi_GPIO_inverted[i] ? 
+                          (bcm2835_gpio_lev(ddlptr->rpi_GPIO[i]) == LOW ? TIOCM_bit[i] : 0)
+                        : (bcm2835_gpio_lev(ddlptr->rpi_GPIO[i]) == HIGH ? TIOCM_bit[i] : 0)
+                        )
+                    : 0);
+            }
+
+            syslog_bus(busnumber, DBG_DEBUG, "reading gpio: TIOCM modem bits = 0x%2x", *argptr);
+
+            break;
+
+        case TIOCMSET:
+
+            syslog_bus(busnumber, DBG_DEBUG, "write gpio: TIOCM modem bits = 0x%2x", *argptr);
+
+            for (int i=0; i<NO_OF_CONTROLLINES; i++ ){
+                if (ddlptr->rpi_GPIO_used[i]&controllines_isoutput[i]) {
+                    if (ddlptr->rpi_GPIO_inverted[i]) {
+                        bcm2835_gpio_write(ddlptr->rpi_GPIO[i], ((*argptr & TIOCM_bit[i]) != 0 ? LOW : HIGH));
+                    }
+                    else{
+                        bcm2835_gpio_write(ddlptr->rpi_GPIO[i], ((*argptr & TIOCM_bit[i]) != 0 ? HIGH : LOW));
+                    }
+                };
+
+            }
+            break;
+    }
+
+    return 0;
+}
+  
+void init_raspi (bus_t busnumber, DDL_DATA* ddlptr)
+ {
+    if (!bcm2835_init()) {
+        syslog_bus(0, DBG_ERROR, "Raspberry PI bcm2835 Lib Init Fail!\n");
+        exit(EXIT_FAILURE);
+    }
+    syslog_bus(busnumber, DBG_DEBUG, "init gpio");
+
+    //GPIO In-Output für Boosterstuerung setzen:
+    for (int i=0; i<NO_OF_CONTROLLINES; i++ ){
+                if (ddlptr->rpi_GPIO_used[i]) {
+                    bcm2835_gpio_fsel(ddlptr->rpi_GPIO[i], 
+                        (controllines_isoutput[i] ? 
+                            BCM2835_GPIO_FSEL_OUTP 
+                            : BCM2835_GPIO_FSEL_INPT)
+                    );
+                    bcm2835_gpio_set_pud(ddlptr->rpi_GPIO[i],
+                        (ddlptr->rpi_GPIO_pullup[i] ?
+                            BCM2835_GPIO_PUD_UP
+                            : (ddlptr->rpi_GPIO_pulldown[i] ?
+                                BCM2835_GPIO_PUD_DOWN
+                                : BCM2835_GPIO_PUD_OFF))
+                    );
+                }
+    }
+ }
+
+int check_rpi_opts(xmlNodePtr child) {
+    int i;
+    for (i=0; i < NO_OF_CONTROLLINES; i++){
+        if (xmlStrcmp(child->name, BAD_CAST rpi_controllines[i])== 0) {
+            break;
+            }
+        }
+    return i;
+}
+
+void interpret_rpi_parameter(int i, xmlChar *txt, bus_t busnumber, DDL_DATA* ddlptr){
+            if (txt != NULL) {
+                ddlptr->rpi_GPIO_used[i] = true;
+                int value = atoi((char *) txt);
+                bool val1 = (value < 0) ;
+                ddlptr->rpi_GPIO_inverted[i] = val1;
+                value = (val1 ? -value : value);
+                ddlptr->rpi_GPIO_pullup[i] = (value >=2000 );
+                value = (value >= 2000 ? value -2000 : value);
+                ddlptr->rpi_GPIO_pulldown[i] = (value >=1000 );
+                ddlptr->rpi_GPIO[i] = (value >= 1000 ? value -1000 : value);
+                syslog_bus(busnumber, DBG_DEBUG, 
+                    "RS232 line %s: Raspberry Pi GPIO %d, inverted: %d, pullup: %d, pulldown: %d", 
+                    rpi_controllines[i],
+                    ddlptr->rpi_GPIO[i], 
+                    (int) ddlptr->rpi_GPIO_inverted[i], 
+                    (int) ddlptr->rpi_GPIO_pullup[i],
+                    (int) ddlptr->rpi_GPIO_pulldown[i]);
+                if (ddlptr->rpi_GPIO[i]>53) {
+                    syslog_bus(busnumber, DBG_ERROR, "Raspberry Pi GPIO out of range");
+                }
+            }
+
+}
+
+#endif
\ Kein Zeilenumbruch am Dateiende.
Index: src/ddl_raspi.h
===================================================================
--- src/ddl_raspi.h	(.../tags/RELEASE_2_1_5)	(nicht existent)
+++ src/ddl_raspi.h	(.../branches/bw-raspidefs)	(Revision 1906)
@@ -0,0 +1,26 @@
+/*
+* This software is published under the terms of the GNU General Public
+* License, Version 2, 1991. (c) Bernd Wagner 18.03.2021.
+*/
+/* for further information see README.raspberrypi */
+
+#include <stdbool.h>
+#include <libxml/tree.h>        /*xmlDocPtr, xmlNodePtr */
+
+#include "config.h"
+#include "config-srcpd.h"
+#include "ddl.h"
+
+#ifdef RASPBERRYPI
+
+#include <bcm2835.h>
+
+extern int ioctl_raspi (int fd, unsigned long int request, int* argptr, bus_t busnumber, DDL_DATA* ddlptr) ;
+
+extern void init_raspi (bus_t busnumber, DDL_DATA* ddlptr) ;
+
+extern int check_rpi_opts(xmlNodePtr child);
+
+extern void interpret_rpi_parameter(int i, xmlChar *txt, bus_t busnumber, DDL_DATA* ddlptr);
+
+#endif
Index: .
===================================================================
--- .	(.../tags/RELEASE_2_1_5)	(Revision 1759)
+++ .	(.../branches/bw-raspidefs)	(Revision 1906)

Eigenschaftsänderungen: .
___________________________________________________________________
Added: svn:mergeinfo
## -0,0 +0,1 ##
   Zusammengeführt /branches/bw-ACKdetection:r1799-1829
