Browse Source

Merge branch 'master' of git://git.drogon.net/wiringPi

Phil Howard 7 years ago
parent
commit
5066e09747

+ 1 - 1
VERSION

@@ -1 +1 @@
-2.32
+2.39

+ 1 - 1
build

@@ -6,7 +6,7 @@
 #	Copyright (c) 2012-2015 Gordon Henderson
 #################################################################################
 # This file is part of wiringPi:
-#	Wiring Compatable library for the Raspberry Pi
+#	A "wiring" library for the Raspberry Pi
 #
 #    wiringPi is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Lesser General Public License as published by

+ 2 - 2
debian-template/wiringPi/DEBIAN/control

@@ -1,5 +1,5 @@
 Package: wiringpi
-Version: 2.32
+Version: 2.38
 Section: libraries
 Priority: optional
 Architecture: armhf
@@ -7,4 +7,4 @@ Depends: libc6
 Maintainer: Gordon Henderson <projects@drogon.net>
 Description: The wiringPi libraries, headers and gpio command
   Libraries to allow GPIO access on a Raspberry Pi from C and C++
-  programs as well as from the command-line
+  and BASIC programs as well as from the command-line

+ 2 - 2
devLib/Makefile

@@ -1,8 +1,8 @@
 #
 # Makefile:
-#	wiringPi device - Wiring Compatable library for the Raspberry Pi
+#	wiringPi device - A "wiring" library for the Raspberry Pi
 #
-#	Copyright (c) 2012-2015 Gordon Henderson
+#	Copyright (c) 2012-2016 Gordon Henderson
 #################################################################################
 # This file is part of wiringPi:
 #	https://projects.drogon.net/raspberry-pi/wiringpi/

+ 1 - 1
devLib/gertboard.c

@@ -101,7 +101,7 @@ int gertboardAnalogRead (const int chan)
 
   wiringPiSPIDataRW (SPI_A2D, spiData, 2) ;
 
-  return ((spiData [0] << 7) | (spiData [1] >> 1)) & 0x3FF ;
+  return ((spiData [0] << 8) | (spiData [1] >> 1)) & 0x3FF ;
 }
 
 

+ 1 - 2
devLib/piFaceOld.c

@@ -1,7 +1,6 @@
 /*
  * piFace.:
- *	Arduino compatable (ish) Wiring library for the Raspberry Pi
- *	Copyright (c) 2012-2013 Gordon Henderson
+ *	Copyright (c) 2012-2016 Gordon Henderson
  *
  *	This file to interface with the PiFace peripheral device which
  *	has an MCP23S17 GPIO device connected via the SPI bus.

+ 1 - 1
examples/Makefile

@@ -1,6 +1,6 @@
 #
 # Makefile:
-#	wiringPi - Wiring Compatable library for the Raspberry Pi
+#	wiringPi - A "wiring" library for the Raspberry Pi
 #	https://projects.drogon.net/wiring-pi
 #
 #	Copyright (c) 2012-2015 Gordon Henderson

+ 2 - 2
examples/PiFace/Makefile

@@ -1,12 +1,12 @@
 #
 # Makefile:
-#	wiringPi - Wiring Compatable library for the Raspberry Pi
+#	wiringPi - A "wiring" library for the Raspberry Pi
 #	https://projects.drogon.net/wiring-pi
 #
 #	Copyright (c) 2012 Gordon Henderson
 #################################################################################
 # This file is part of wiringPi:
-#	Wiring Compatable library for the Raspberry Pi
+#	A "wiring" library for the Raspberry Pi
 #
 #    wiringPi is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Lesser General Public License as published by

+ 2 - 2
examples/PiGlow/Makefile

@@ -1,12 +1,12 @@
 #
 # Makefile:
-#	wiringPi - Wiring Compatable library for the Raspberry Pi
+#	wiringPi - A "wiring" library for the Raspberry Pi
 #	https://projects.drogon.net/wiring-pi
 #
 #	Copyright (c) 2012-2015 Gordon Henderson
 #################################################################################
 # This file is part of wiringPi:
-#	Wiring Compatable library for the Raspberry Pi
+#	A "wiring" library for the Raspberry Pi
 #
 #    wiringPi is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Lesser General Public License as published by

+ 2 - 2
examples/q2w/Makefile

@@ -1,12 +1,12 @@
 #
 # Makefile:
-#	wiringPi - Wiring Compatable library for the Raspberry Pi
+#	wiringPi - A "wiring" library for the Raspberry Pi
 #	https://projects.drogon.net/wiring-pi
 #
 #	Copyright (c) 2012-2013 Gordon Henderson
 #################################################################################
 # This file is part of wiringPi:
-#	Wiring Compatable library for the Raspberry Pi
+#	A "wiring" library for the Raspberry Pi
 #
 #    wiringPi is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Lesser General Public License as published by

+ 2 - 2
examples/scrollPhat/Makefile

@@ -1,12 +1,12 @@
 #
 # Makefile:
-#	wiringPi - Wiring Compatable library for the Raspberry Pi
+#	wiringPi - A "wiring" library for the Raspberry Pi
 #	https://projects.drogon.net/wiring-pi
 #
 #	Copyright (c) 2012-2015 Gordon Henderson
 #################################################################################
 # This file is part of wiringPi:
-#	Wiring Compatable library for the Raspberry Pi
+#	A "wiring" library for the Raspberry Pi
 #
 #    wiringPi is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Lesser General Public License as published by

+ 7 - 5
gpio/Makefile

@@ -4,10 +4,10 @@
 #	  A swiss-army knige of GPIO shenanigans.
 #	https://projects.drogon.net/wiring-pi
 #
-#	Copyright (c) 2012-2015 Gordon Henderson
+#	Copyright (c) 2012-2016 Gordon Henderson
 #################################################################################
 # This file is part of wiringPi:
-#	Wiring Compatable library for the Raspberry Pi
+#	A "wiring" library for the Raspberry Pi
 #
 #    wiringPi is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Lesser General Public License as published by
@@ -34,10 +34,10 @@ endif
 DEBUG	= -O2
 CC	= gcc
 INCLUDE	= -I$(DESTDIR)$(PREFIX)/include
-CFLAGS	= $(DEBUG) -Wall $(INCLUDE) -Winline -pipe
+CFLAGS	= $(DEBUG) -Wall -Wextra $(INCLUDE) -Winline -pipe
 
 LDFLAGS	= -L$(DESTDIR)$(PREFIX)/lib
-LIBS    = -lwiringPi -lwiringPiDev -lpthread
+LIBS    = -lwiringPi -lwiringPiDev -lpthread -lrt -lm
 
 # May not need to  alter anything below this line
 ###############################################################################
@@ -85,6 +85,8 @@ install-deb:	gpio
 	$Q echo "[Install: deb]"
 	$Q install -m 0755 -d							~/wiringPi/debian-template/wiringPi/usr/bin
 	$Q install -m 0755 gpio							~/wiringPi/debian-template/wiringPi/usr/bin
+	$Q install -m 0755 -d							~/wiringPi/debian-template/wiringPi/man/man1
+	$Q install -m 0644 gpio.1						~/wiringPi/debian-template/wiringPi/man/man1
 
 .PHONY:	uninstall
 uninstall:
@@ -98,4 +100,4 @@ depend:
 
 # DO NOT DELETE
 
-gpio.o: version.h
+gpio.o: ../version.h

+ 145 - 25
gpio/gpio.c

@@ -2,7 +2,7 @@
  * gpio.c:
  *	Swiss-Army-Knife, Set-UID command-line interface to the Raspberry
  *	Pi's GPIO.
- *	Copyright (c) 2012-2015 Gordon Henderson
+ *	Copyright (c) 2012-2017 Gordon Henderson
  ***********************************************************************
  * This file is part of wiringPi:
  *	https://projects.drogon.net/raspberry-pi/wiringpi/
@@ -40,7 +40,7 @@
 #include <gertboard.h>
 #include <piFace.h>
 
-#include "version.h"
+#include "../version.h"
 
 extern int wiringPiDebug ;
 
@@ -57,14 +57,19 @@ extern void doPins       (void) ;
 
 #define	PI_USB_POWER_CONTROL	38
 #define	I2CDETECT		"/usr/sbin/i2cdetect"
+#define	MODPROBE		"/sbin/modprobe"
+#define	RMMOD			"/sbin/rmmod"
 
 int wpMode ;
 
 char *usage = "Usage: gpio -v\n"
               "       gpio -h\n"
-              "       gpio [-g|-1] [-x extension:params] ...\n"
+              "       gpio [-g|-1] ...\n"
+              "       gpio [-d] ...\n"
+              "       [-x extension:params] [[ -x ...]] ...\n"
               "       gpio [-p] <read/write/wb> ...\n"
               "       gpio <read/write/aread/awritewb/pwm/clock/mode> ...\n"
+              "       gpio <toggle/blink> <pin>\n"
 	      "       gpio readall/reset\n"
 	      "       gpio unexportall/exports\n"
 	      "       gpio export/edge/unexport ...\n"
@@ -76,6 +81,8 @@ char *usage = "Usage: gpio -v\n"
 	      "       gpio load spi/i2c\n"
 	      "       gpio unload spi/i2c\n"
 	      "       gpio i2cd/i2cdetect\n"
+	      "       gpio rbx/rbd\n"
+	      "       gpio wb <value>\n"
 	      "       gpio usbp high/low\n"
 	      "       gpio gbr <channel>\n"
 	      "       gpio gbw <channel> <value>" ;	// No trailing newline needed here.
@@ -102,6 +109,45 @@ static int decodePin (const char *str)
 #endif
 
 
+/*
+ * findExecutable:
+ *	Code to locate the path to the given executable. We have a fixed list
+ *	of locations to try which completely overrides any $PATH environment.
+ *	This may be detrimental, however it avoids the reliance on $PATH
+ *	which may be a security issue when this program is run a set-uid-root.
+ *********************************************************************************
+ */
+
+static const char *searchPath [] =
+{
+  "/sbin",
+  "/usr/sbin",
+  "/bin",
+  "/usr/bin",
+  NULL,
+} ;
+
+static char *findExecutable (const char *progName)
+{
+  static char *path = NULL ;
+  int len = strlen (progName) ;
+  int i = 0 ;
+  struct stat statBuf ;
+
+  for (i = 0 ; searchPath [i] != NULL ; ++i)
+  {
+    path = malloc (strlen (searchPath [i]) + len + 2) ;
+    sprintf (path, "%s/%s", searchPath [i], progName) ;
+
+    if (stat (path, &statBuf) == 0)
+      return path ;
+    free (path) ;
+  }
+
+  return NULL ;
+}
+
+
 /*
  * changeOwner:
  *	Change the ownership of the file to the real userId of the calling
@@ -230,15 +276,18 @@ static void doLoad (int argc, char *argv [])
   else
     _doLoadUsage (argv) ;
 
+  if (findExecutable ("modprobe") == NULL)
+    printf ("No found\n") ;
+
   if (!moduleLoaded (module1))
   {
-    sprintf (cmd, "/sbin/modprobe %s%s", module1, args1) ;
+    sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module1, args1) ;
     system (cmd) ;
   }
 
   if (!moduleLoaded (module2))
   {
-    sprintf (cmd, "/sbin/modprobe %s%s", module2, args2) ;
+    sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module2, args2) ;
     system (cmd) ;
   }
 
@@ -292,13 +341,13 @@ static void doUnLoad (int argc, char *argv [])
 
   if (moduleLoaded (module1))
   {
-    sprintf (cmd, "/sbin/rmmod %s", module1) ;
+    sprintf (cmd, "%s %s", findExecutable (RMMOD), module1) ;
     system (cmd) ;
   }
 
   if (moduleLoaded (module2))
   {
-    sprintf (cmd, "/sbin/rmmod %s", module2) ;
+    sprintf (cmd, "%s %s", findExecutable (RMMOD), module2) ;
     system (cmd) ;
   }
 }
@@ -310,13 +359,12 @@ static void doUnLoad (int argc, char *argv [])
  *********************************************************************************
  */
 
-static void doI2Cdetect (int argc, char *argv [])
+static void doI2Cdetect (UNU int argc, char *argv [])
 {
-  int port = piBoardRev () == 1 ? 0 : 1 ;
-  char command [128] ;
-  struct stat statBuf ;
+  int port = piGpioLayout () == 1 ? 0 : 1 ;
+  char *c, *command ;
 
-  if (stat (I2CDETECT, &statBuf) < 0)
+  if ((c = findExecutable (I2CDETECT)) == NULL)
   {
     fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ;
     return ;
@@ -328,7 +376,8 @@ static void doI2Cdetect (int argc, char *argv [])
     return ;
   }
 
-  sprintf (command, "%s -y %d", I2CDETECT, port) ;
+  command = malloc (strlen (c) + 16) ;
+  sprintf (command, "%s -y %d", c, port) ;
   if (system (command) < 0)
     fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ;
 
@@ -341,7 +390,7 @@ static void doI2Cdetect (int argc, char *argv [])
  *********************************************************************************
  */
 
-static void doExports (int argc, char *argv [])
+static void doExports (UNU int argc, UNU char *argv [])
 {
   int fd ;
   int i, l, first ;
@@ -667,7 +716,7 @@ void doUnexportall (char *progName)
  *********************************************************************************
  */
 
-static void doReset (char *progName)
+static void doReset (UNU char *progName)
 {
   printf ("GPIO Reset is dangerous and has been removed from the gpio command.\n") ;
   printf (" - Please write a shell-script to reset the GPIO pins into the state\n") ;
@@ -943,7 +992,7 @@ static void doAwrite (int argc, char *argv [])
 
 /*
  * doWriteByte:
- *	gpio write value
+ *	gpio wb value
  *********************************************************************************
  */
 
@@ -963,6 +1012,30 @@ static void doWriteByte (int argc, char *argv [])
 }
 
 
+/*
+ * doReadByte:
+ *	gpio rbx|rbd value
+ *********************************************************************************
+ */
+
+static void doReadByte (int argc, char *argv [], int printHex)
+{
+  int val ;
+
+  if (argc != 2)
+  {
+    fprintf (stderr, "Usage: %s rbx|rbd\n", argv [0]) ;
+    exit (1) ;
+  }
+
+  val = digitalReadByte () ;
+  if (printHex)
+    printf ("%02X\n", val) ;
+  else
+    printf ("%d\n", val) ;
+}
+
+
 /*
  * doRead:
  *	Read a pin and return the value
@@ -1026,6 +1099,34 @@ void doToggle (int argc, char *argv [])
 }
 
 
+/*
+ * doBlink:
+ *	Blink an IO pin
+ *********************************************************************************
+ */
+
+void doBlink (int argc, char *argv [])
+{
+  int pin ;
+
+  if (argc != 3)
+  {
+    fprintf (stderr, "Usage: %s blink pin\n", argv [0]) ;
+    exit (1) ;
+  }
+
+  pin = atoi (argv [2]) ;
+
+  pinMode (pin, OUTPUT) ;
+  for (;;)
+  {
+    digitalWrite (pin, !digitalRead (pin)) ;
+    delay (500) ;
+  }
+
+}
+
+
 /*
  * doPwmTone:
  *	Output a tone in a PWM pin
@@ -1162,9 +1263,14 @@ static void doVersion (char *argv [])
 {
   int model, rev, mem, maker, warranty ;
   struct stat statBuf ;
+  char name [80] ;
+  FILE *fd ;
 
-  printf ("gpio version: %s\n", VERSION) ;
-  printf ("Copyright (c) 2012-2015 Gordon Henderson\n") ;
+  int vMaj, vMin ;
+
+  wiringPiVersion (&vMaj, &vMin) ;
+  printf ("gpio version: %d.%d\n", vMaj, vMin) ;
+  printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ;
   printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
   printf ("For details type: %s -warranty\n", argv [0]) ;
   printf ("\n") ;
@@ -1179,12 +1285,18 @@ static void doVersion (char *argv [])
   if (stat ("/proc/device-tree", &statBuf) == 0)	// We're on a devtree system ...
     printf ("  * Device tree is enabled.\n") ;
 
-  if (stat ("/dev/gpiomem", &statBuf) == 0)		// User level GPIO is GO
+  if (stat ("/proc/device-tree/model", &statBuf) == 0)	// Output Kernel idea of board type
   {
-    printf ("  * This Raspberry Pi supports user-level GPIO access.\n") ;
-    printf ("    -> See the man-page for more details\n") ;
-    printf ("    -> ie. export WIRINGPI_GPIOMEM=1\n") ;
+    if ((fd = fopen ("/proc/device-tree/model", "r")) != NULL)
+    {
+      fgets (name, 80, fd) ;
+      fclose (fd) ;
+      printf ("  *--> %s\n", name) ;
+    }
   }
+
+  if (stat ("/dev/gpiomem", &statBuf) == 0)		// User level GPIO is GO
+    printf ("  * This Raspberry Pi supports user-level GPIO access.\n") ;
   else
     printf ("  * Root or sudo required for GPIO access.\n") ;
 }
@@ -1225,7 +1337,7 @@ int main (int argc, char *argv [])
 
   if ((strcmp (argv [1], "-R") == 0) || (strcmp (argv [1], "-V") == 0))
   {
-    printf ("%d\n", piBoardRev ()) ;
+    printf ("%d\n", piGpioLayout ()) ;
     return 0 ;
   }
 
@@ -1240,7 +1352,7 @@ int main (int argc, char *argv [])
   if (strcasecmp (argv [1], "-warranty") == 0)
   {
     printf ("gpio version: %s\n", VERSION) ;
-    printf ("Copyright (c) 2012-2015 Gordon Henderson\n") ;
+    printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ;
     printf ("\n") ;
     printf ("    This program is free software; you can redistribute it and/or modify\n") ;
     printf ("    it under the terms of the GNU Leser General Public License as published\n") ;
@@ -1340,8 +1452,11 @@ int main (int argc, char *argv [])
   }
 
 // Check for -x argument to load in a new extension
+//	-x extension:base:args
+//	Can load many modules, but unless daemon mode we can only send one
+//	command at a time.
 
-  if (strcasecmp (argv [1], "-x") == 0)
+  while (strcasecmp (argv [1], "-x") == 0)
   {
     if (argc < 3)
     {
@@ -1352,6 +1467,8 @@ int main (int argc, char *argv [])
     if (!loadWPiExtension (argv [0], argv [2], TRUE))	// Prints its own error messages
       exit (EXIT_FAILURE) ;
 
+// Shift args down by 2
+
     for (i = 3 ; i < argc ; ++i)
       argv [i - 2] = argv [i] ;
     argc -= 2 ;
@@ -1375,6 +1492,7 @@ int main (int argc, char *argv [])
 // GPIO Nicies
 
   else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle    (argc, argv) ;
+  else if (strcasecmp (argv [1], "blink"  ) == 0) doBlink     (argc, argv) ;
 
 // Pi Specifics
 
@@ -1391,6 +1509,8 @@ int main (int argc, char *argv [])
   else if (strcasecmp (argv [1], "i2cd"     ) == 0) doI2Cdetect  (argc, argv) ;
   else if (strcasecmp (argv [1], "reset"    ) == 0) doReset      (argv [0]) ;
   else if (strcasecmp (argv [1], "wb"       ) == 0) doWriteByte  (argc, argv) ;
+  else if (strcasecmp (argv [1], "rbx"      ) == 0) doReadByte   (argc, argv, TRUE) ;
+  else if (strcasecmp (argv [1], "rbd"      ) == 0) doReadByte   (argc, argv, FALSE) ;
   else if (strcasecmp (argv [1], "clock"    ) == 0) doClock      (argc, argv) ;
   else if (strcasecmp (argv [1], "wfi"      ) == 0) doWfi        (argc, argv) ;
   else

+ 1 - 1
gpio/pins.c

@@ -1,7 +1,7 @@
 /*
  * pins.c:
  *	Just display a handy Pi pinnout diagram.
- *	Copyright (c) 2012-2015 Gordon Henderson
+ *	Copyright (c) 2012-2017 Gordon Henderson
  ***********************************************************************
  * This file is part of wiringPi:
  *	https://projects.drogon.net/raspberry-pi/wiringpi/

+ 1 - 1
gpio/pintest

@@ -5,7 +5,7 @@
 # Copyright (c) 2013-2015 Gordon Henderson
 #################################################################################
 # This file is part of wiringPi:
-#	Wiring Compatable library for the Raspberry Pi
+#	A "wiring" library for the Raspberry Pi
 #
 #    wiringPi is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Lesser General Public License as published by

+ 3 - 3
gpio/readall.c

@@ -1,7 +1,7 @@
 /*
  * readall.c:
  *	The readall functions - getting a bit big, so split them out.
- *	Copyright (c) 2012-2015 Gordon Henderson
+ *	Copyright (c) 2012-2017 Gordon Henderson
  ***********************************************************************
  * This file is part of wiringPi:
  *	https://projects.drogon.net/raspberry-pi/wiringpi/
@@ -118,7 +118,7 @@ static char *physNames [64] =
   NULL,
 
   "   3.3v", "5v     ",
-  "  SDA.1", "5V     ",
+  "  SDA.1", "5v     ",
   "  SCL.1", "0v     ",
   "GPIO. 7", "TxD    ",
   "     0v", "RxD    ",
@@ -348,7 +348,7 @@ void doReadall (void)
     abReadall (model, rev) ;
   else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || (model == PI_MODEL_2) || (model == PI_MODEL_3) || (model == PI_MODEL_ZERO))
     piPlusReadall (model) ;
-  else if (model == PI_MODEL_CM)
+  else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3))
     allReadall () ;
   else
     printf ("Oops - unable to determine board type... model: %d\n", model) ;

+ 1 - 1
gpio/test.sh

@@ -5,7 +5,7 @@
 #	in-turn.
 #################################################################################
 # This file is part of wiringPi:
-#	Wiring Compatable library for the Raspberry Pi
+#	A "wiring" library for the Raspberry Pi
 #
 #    wiringPi is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Lesser General Public License as published by

+ 0 - 1
gpio/version.h

@@ -1 +0,0 @@
-#define VERSION "2.32"

+ 8 - 4
newVersion

@@ -7,7 +7,7 @@
 #	Copyright (c) 2012-2015 Gordon Henderson
 #################################################################################
 # This file is part of wiringPi:
-#	Wiring Compatable library for the Raspberry Pi
+#	A "wiring" library for the Raspberry Pi
 #
 #    wiringPi is free software: you can redistribute it and/or modify
 #    it under the terms of the GNU Lesser General Public License as published by
@@ -25,8 +25,12 @@
 
 echo Updating to version: `cat VERSION`
 
-rm -f gpio/version.h
-echo "#define VERSION \"`cat VERSION`\"" > gpio/version.h
+rm -f version.h
+vMaj=`cut -d. -f1 VERSION`
+vMin=`cut -d. -f2 VERSION`
+echo "#define VERSION \"`cat VERSION`\"" > version.h
+echo "#define VERSION_MAJOR $vMaj"		>> version.h
+echo "#define VERSION_MINOR $vMin"		>> version.h
 
 rm -f debian-template/wiringPi/DEBIAN/control
 cat > debian-template/wiringPi/DEBIAN/control <<EOF
@@ -39,5 +43,5 @@ Depends: libc6
 Maintainer: Gordon Henderson <projects@drogon.net>
 Description: The wiringPi libraries, headers and gpio command
   Libraries to allow GPIO access on a Raspberry Pi from C and C++
-  programs as well as from the command-line
+  and BASIC programs as well as from the command-line
 EOF

+ 5 - 0
update

@@ -0,0 +1,5 @@
+#!/bin/sh
+
+# update - update source files from master on yakko
+
+rsync -aHx --exclude='*.o' --exclude='*~' -v --delete gordon@yakko:rpi/git/wiringPi/ .

+ 3 - 0
version.h

@@ -0,0 +1,3 @@
+#define VERSION "2.38"
+#define VERSION_MAJOR 2
+#define VERSION_MINOR 38

+ 15 - 20
wiringPi/Makefile

@@ -39,9 +39,9 @@ DEBUG	= -O2
 CC	= gcc
 INCLUDE	= -I.
 DEFS	= -D_GNU_SOURCE
-CFLAGS	= $(DEBUG) $(DEFS) -Wformat=2 -Wall -Winline $(INCLUDE) -pipe -fPIC
+CFLAGS	= $(DEBUG) $(DEFS) -Wformat=2 -Wall -Wextra -Winline $(INCLUDE) -pipe -fPIC
 
-LIBS    =
+LIBS    = -lm -lpthread -lrt
 
 ###############################################################################
 
@@ -57,23 +57,12 @@ SRC	=	wiringPi.c						\
 		mcp3002.c mcp3004.c mcp4802.c mcp3422.c			\
 		max31855.c max5322.c ads1115.c				\
 		sn3218.c						\
+		bmp180.c htu21d.c ds18b20.c				\
 		drcSerial.c						\
+		pseudoPins.c						\
 		wpiExtensions.c
 
-HEADERS =	wiringPi.h						\
-		wiringSerial.h wiringShift.h				\
-		wiringPiSPI.h wiringPiI2C.h				\
-		softPwm.h softTone.h					\
-		mcp23008.h mcp23016.h mcp23017.h			\
-		mcp23s08.h mcp23s17.h					\
-		sr595.h							\
-		pcf8574.h pcf8591.h					\
-		mcp3002.h mcp3004.h mcp4802.h mcp3422.h			\
-		max31855.h max5322.h ads1115.h				\
-		sn3218.h						\
-		drcSerial.h						\
-		wpiExtensions.h 
-
+HEADERS =	$(shell ls *.h)
 
 OBJ	=	$(SRC:.c=.o)
 
@@ -89,7 +78,7 @@ $(STATIC):	$(OBJ)
 
 $(DYNAMIC):	$(OBJ)
 	$Q echo "[Link (Dynamic)]"
-	$Q $(CC) -shared -Wl,-soname,libwiringPi.so$(WIRINGPI_SONAME_SUFFIX) -o libwiringPi.so.$(VERSION) -lpthread $(OBJ)
+	$Q $(CC) -shared -Wl,-soname,libwiringPi.so$(WIRINGPI_SONAME_SUFFIX) -o libwiringPi.so.$(VERSION) $(LIBS) $(OBJ)
 
 .c.o:
 	$Q echo [Compile] $<
@@ -151,7 +140,7 @@ depend:
 
 # DO NOT DELETE
 
-wiringPi.o: softPwm.h softTone.h wiringPi.h
+wiringPi.o: softPwm.h softTone.h wiringPi.h ../version.h
 wiringSerial.o: wiringSerial.h
 wiringShift.o: wiringPi.h wiringShift.h
 piHiPri.o: wiringPi.h
@@ -174,9 +163,15 @@ mcp4802.o: wiringPi.h wiringPiSPI.h mcp4802.h
 mcp3422.o: wiringPi.h wiringPiI2C.h mcp3422.h
 max31855.o: wiringPi.h wiringPiSPI.h max31855.h
 max5322.o: wiringPi.h wiringPiSPI.h max5322.h
+ads1115.o: wiringPi.h wiringPiI2C.h ads1115.h
 sn3218.o: wiringPi.h wiringPiI2C.h sn3218.h
+bmp180.o: wiringPi.h wiringPiI2C.h bmp180.h
+htu21d.o: wiringPi.h wiringPiI2C.h htu21d.h
+ds18b20.o: wiringPi.h ds18b20.h
 drcSerial.o: wiringPi.h wiringSerial.h drcSerial.h
+pseudoPins.o: wiringPi.h pseudoPins.h
 wpiExtensions.o: wiringPi.h mcp23008.h mcp23016.h mcp23017.h mcp23s08.h
 wpiExtensions.o: mcp23s17.h sr595.h pcf8574.h pcf8591.h mcp3002.h mcp3004.h
-wpiExtensions.o: mcp4802.h mcp3422.h max31855.h max5322.h sn3218.h
-wpiExtensions.o: drcSerial.h wpiExtensions.h
+wpiExtensions.o: mcp4802.h mcp3422.h max31855.h max5322.h ads1115.h sn3218.h
+wpiExtensions.o: drcSerial.h pseudoPins.h bmp180.h htu21d.h ds18b20.h
+wpiExtensions.o: wpiExtensions.h

+ 1 - 1
wiringPi/ads1115.c

@@ -228,7 +228,7 @@ static void myDigitalWrite (struct wiringPiNodeStruct *node, int pin, int data)
   {
     if ( (data < 0) || (data > 7) )	// Use default if out of range
       data = 4 ;
-    node->data0 = dataRates [data] ;
+    node->data1 = dataRates [data] ;	// Bugfix 0-1 by "Eric de jong (gm)" <ericdejong@gmx.net> - Thanks.
   }
   
 }

+ 237 - 0
wiringPi/bmp180.c

@@ -0,0 +1,237 @@
+/*
+ * bmp180.c:
+ *	Extend wiringPi with the BMP180 I2C Pressure and Temperature
+ *	sensor. This is used in the Pi Weather Station
+ *	Copyright (c) 2016 Gordon Henderson
+ *
+ *	Information from the document held at:
+ *		http://wmrx00.sourceforge.net/Arduino/BMP085-Calcs.pdf
+ *	was very useful when building this code.
+ *
+ ***********************************************************************
+ * This file is part of wiringPi:
+ *	https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ *    wiringPi is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as
+ *    published by the Free Software Foundation, either version 3 of the
+ *    License, or (at your option) any later version.
+ *
+ *    wiringPi is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public
+ *    License along with wiringPi.
+ *    If not, see <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#include <unistd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "wiringPi.h"
+#include "wiringPiI2C.h"
+
+#include "bmp180.h"
+
+#undef	DEBUG
+
+#define	I2C_ADDRESS	0x77
+#define	BMP180_OSS	   0
+
+
+// Static calibration data
+//	The down-side of this is that there can only be one BMP180 in
+//	a system - which is practice isn't an issue as it's I2C
+//	address is fixed.
+
+static  int16_t AC1, AC2, AC3 ;
+static uint16_t AC4, AC5, AC6 ;
+static  int16_t VB1, VB2 ;
+static  int16_t  MB,  MC, MD ;
+
+static double c5, c6, mc, md, x0, x1, x2, yy0, yy1, yy2, p0, p1, p2 ;
+
+// Pressure & Temp variables
+
+uint32_t cPress, cTemp ;
+
+static int altitude ;
+
+/*
+ * read16:
+ *	Quick hack to read the 16-bit data with the correct endian
+ *********************************************************************************
+ */
+
+uint16_t read16 (int fd, int reg)
+{
+  return (wiringPiI2CReadReg8 (fd, reg) <<  8) | wiringPiI2CReadReg8 (fd, reg + 1) ;
+
+}
+
+
+/*
+ * bmp180ReadTempPress:
+ *	Does the hard work of reading the sensor
+ *********************************************************************************
+ */
+
+static void bmp180ReadTempPress (int fd)
+{
+  double fTemp, fPress ;
+  double tu, a ;
+  double pu, s, x, y, z ;
+
+  uint8_t data [4] ;
+
+// Start a temperature sensor reading
+
+  wiringPiI2CWriteReg8 (fd, 0xF4, 0x2E) ;
+  delay (5) ;
+
+// Read the raw data
+
+  data [0] = wiringPiI2CReadReg8 (fd, 0xF6) ;
+  data [1] = wiringPiI2CReadReg8 (fd, 0xF7) ;
+
+// And calculate...
+
+  tu = (data [0] * 256.0) + data [1] ;
+
+  a = c5 * (tu - c6) ;
+  fTemp = a + (mc / (a + md)) ;
+  cTemp = (int)rint (((100.0 * fTemp) + 0.5) / 10.0) ;
+
+#ifdef	DEBUG
+  printf ("fTemp: %f, cTemp: %6d\n", fTemp, cTemp) ;
+#endif
+
+// Start a pressure snsor reading
+
+  wiringPiI2CWriteReg8 (fd, 0xF4, 0x34 | (BMP180_OSS << 6)) ;
+  delay (5) ;
+
+// Read the raw data
+
+  data [0] = wiringPiI2CReadReg8 (fd, 0xF6) ;
+  data [1] = wiringPiI2CReadReg8 (fd, 0xF7) ;
+  data [2] = wiringPiI2CReadReg8 (fd, 0xF8) ;
+
+// And calculate...
+
+  pu = ((double)data [0] * 256.0) + (double)data [1] + ((double)data [2] / 256.0) ;
+  s = fTemp - 25.0 ;
+  x = (x2 * pow (s, 2.0)) + (x1 * s) + x0 ;
+  y = (yy2 * pow (s, 2.0)) + (yy1 * s) + yy0 ;
+  z = (pu - x) / y ;
+  fPress = (p2 * pow (z, 2.0)) + (p1 * z) + p0 ;
+  cPress = (int)rint (((100.0 * fPress) + 0.5) / 10.0) ;
+
+#ifdef	DEBUG
+  printf ("fPress: %f, cPress: %6d\n", fPress, cPress) ;
+#endif
+}
+
+
+/*
+ * myAnalogWrite:
+ *	Write to a fake register to represent the height above sea level
+ *	so that the peudo millibar register can read the pressure in mB
+ *********************************************************************************
+ */
+
+static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value)
+{
+  int chan = pin - node->pinBase ;
+
+  if (chan == 0)
+    altitude = value ;
+}
+
+/*
+ * myAnalogRead:
+ *********************************************************************************
+ */
+
+static int myAnalogRead (struct wiringPiNodeStruct *node, int pin)
+{
+  int chan = pin - node->pinBase ;
+
+  bmp180ReadTempPress (node->fd) ;
+
+  /**/ if (chan == 0)	// Read Temperature
+    return cTemp ;
+  else if (chan == 1)	// Pressure
+    return cPress ;
+  else if (chan == 2)	// Pressure in mB
+    return cPress / pow (1 - ((double)altitude / 44330.0), 5.255) ;
+  else
+    return -9999 ;
+
+}
+
+
+/*
+ * bmp180Setup:
+ *	Create a new instance of a PCF8591 I2C GPIO interface. We know it
+ *	has 4 pins, (4 analog inputs and 1 analog output which we'll shadow
+ *	input 0) so all we need to know here is the I2C address and the
+ *	user-defined pin base.
+ *********************************************************************************
+ */
+
+int bmp180Setup (const int pinBase)
+{
+  double c3, c4, b1 ;
+  int fd ;
+  struct wiringPiNodeStruct *node ;
+
+  if ((fd = wiringPiI2CSetup (I2C_ADDRESS)) < 0)
+    return FALSE ;
+
+  node = wiringPiNewNode (pinBase, 4) ;
+
+  node->fd          = fd ;
+  node->analogRead  = myAnalogRead ;
+  node->analogWrite = myAnalogWrite ;
+
+// Read calibration data
+
+  AC1 = read16 (fd, 0xAA) ;
+  AC2 = read16 (fd, 0xAC) ;
+  AC3 = read16 (fd, 0xAE) ;
+  AC4 = read16 (fd, 0xB0) ;
+  AC5 = read16 (fd, 0xB2) ;
+  AC6 = read16 (fd, 0xB4) ;
+  VB1 = read16 (fd, 0xB6) ;
+  VB2 = read16 (fd, 0xB8) ;
+   MB = read16 (fd, 0xBA) ;
+   MC = read16 (fd, 0xBC) ;
+   MD = read16 (fd, 0xBE) ;
+
+// Calculate coefficients
+
+  c3 = 160.0 * pow (2.0, -15.0) * AC3 ;
+  c4 = pow (10.0, -3.0) * pow(2.0,-15.0) * AC4 ;
+  b1 = pow (160.0, 2.0) * pow(2.0,-30.0) * VB1 ;
+  c5 = (pow (2.0, -15.0) / 160.0) * AC5 ;
+  c6 = AC6 ;
+  mc = (pow (2.0, 11.0) / pow(160.0,2.0)) * MC ;
+  md = MD / 160.0 ;
+  x0 = AC1 ;
+  x1 = 160.0 * pow (2.0, -13.0) * AC2 ;
+  x2 = pow (160.0, 2.0) * pow(2.0,-25.0) * VB2 ;
+  yy0 = c4 * pow (2.0, 15.0) ;
+  yy1 = c4 * c3 ;
+  yy2 = c4 * b1 ;
+  p0 = (3791.0 - 8.0) / 1600.0 ;
+  p1 = 1.0 - 7357.0 * pow (2.0, -20.0) ;
+  p2 = 3038.0 * 100.0 * pow (2.0,  -36.0) ;
+
+  return TRUE ;
+}

+ 34 - 0
wiringPi/bmp180.h

@@ -0,0 +1,34 @@
+/*
+ * bmp180.h:
+ *	Extend wiringPi with the BMP180 I2C Pressure and Temperature
+ *	sensor.
+ *	Copyright (c) 2016 Gordon Henderson
+ ***********************************************************************
+ * This file is part of wiringPi:
+ *	https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ *    wiringPi is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as
+ *    published by the Free Software Foundation, either version 3 of the
+ *    License, or (at your option) any later version.
+ *
+ *    wiringPi is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public
+ *    License along with wiringPi.
+ *    If not, see <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int bmp180Setup (const int pinBase) ;
+
+#ifdef __cplusplus
+}
+#endif

+ 146 - 0
wiringPi/ds18b20.c

@@ -0,0 +1,146 @@
+/*
+ * ds18b20.c:
+ *	Extend wiringPi with the DS18B20 1-Wire temperature sensor.
+ *	This is used in the Pi Weather Station and many other places.
+ *	Copyright (c) 2016 Gordon Henderson
+ ***********************************************************************
+ * This file is part of wiringPi:
+ *	https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ *    wiringPi is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as
+ *    published by the Free Software Foundation, either version 3 of the
+ *    License, or (at your option) any later version.
+ *
+ *    wiringPi is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public
+ *    License along with wiringPi.
+ *    If not, see <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <unistd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include <malloc.h>
+#include <ctype.h>
+
+#include "wiringPi.h"
+
+#include "ds18b20.h"
+
+#define	W1_PREFIX	"/sys/bus/w1/devices/28-"
+#define	W1_POSTFIX	"/w1_slave"
+
+
+/*
+ * myAnalogRead:
+ *********************************************************************************
+ */
+
+static int myAnalogRead (struct wiringPiNodeStruct *node, int pin)
+{
+  int  chan = pin - node->pinBase ;
+  int  fd = node->fd ;
+  char buffer [4096] ;
+  char *p ;
+  int  temp, sign ;
+
+  if (chan != 0)
+    return -9999 ;
+
+// Rewind the file - we're keeping it open to keep things going
+//	smoothly
+
+  lseek (fd, 0, SEEK_SET) ;
+
+// Read the file - we know it's only a couple of lines, so this ought to be
+//	more than enough
+
+  if (read (fd, buffer, 4096) <= 0)	// Read nothing, or it failed in some odd way
+    return -9998 ;
+
+// Look for YES, then t=
+
+  if (strstr (buffer, "YES") == NULL)
+    return -9997 ;
+
+  if ((p = strstr (buffer, "t=")) == NULL)
+    return -9996 ;
+
+// p points to the 't', so we skip over it...
+
+  p += 2 ;
+
+// and extract the number
+//	(without caring about overflow)
+
+
+  if (*p == '-')	// Negative number?
+  {
+    sign = -1 ;
+    ++p ;
+  }
+  else
+    sign = 1 ;
+
+  temp = 0 ;
+  while (isdigit (*p))
+  {
+    temp = temp * 10 + (*p - '0') ;
+    ++p ;
+  }
+
+// We know it returns temp * 1000, but we only really want temp * 10, so
+//	do a bit of rounding...
+
+  temp = (temp + 50) / 100 ;
+  return temp * sign ;
+}
+
+
+/*
+ * ds18b20Setup:
+ *	Create a new instance of a DS18B20 temperature sensor.
+ *********************************************************************************
+ */
+
+int ds18b20Setup (const int pinBase, const char *deviceId)
+{
+  int fd ;
+  struct wiringPiNodeStruct *node ;
+  char *fileName ;
+
+// Allocate space for the filename
+
+  if ((fileName = malloc (strlen (W1_PREFIX) + strlen (W1_POSTFIX) + strlen (deviceId) + 1)) == NULL)
+    return FALSE ;
+
+  sprintf (fileName, "%s%s%s", W1_PREFIX, deviceId, W1_POSTFIX) ;
+
+  fd = open (fileName, O_RDONLY) ;
+
+  free (fileName) ;
+
+  if (fd < 0)
+    return FALSE ;
+
+// We'll keep the file open, to make access a little faster
+//	although it's very slow reading these things anyway )-:
+
+  node = wiringPiNewNode (pinBase, 1) ;
+
+  node->fd         = fd ;
+  node->analogRead = myAnalogRead ;
+
+  return TRUE ;
+}

+ 34 - 0
wiringPi/ds18b20.h

@@ -0,0 +1,34 @@
+/*
+ * bmp180.h:
+ *	Extend wiringPi with the BMP180 I2C Pressure and Temperature
+ *	sensor.
+ *	Copyright (c) 2016 Gordon Henderson
+ ***********************************************************************
+ * This file is part of wiringPi:
+ *	https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ *    wiringPi is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as
+ *    published by the Free Software Foundation, either version 3 of the
+ *    License, or (at your option) any later version.
+ *
+ *    wiringPi is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public
+ *    License along with wiringPi.
+ *    If not, see <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int ds18b20Setup (const int pinBase, const char *serialNum) ;
+
+#ifdef __cplusplus
+}
+#endif

+ 150 - 0
wiringPi/htu21d.c

@@ -0,0 +1,150 @@
+/*
+ * htu21d.c:
+ *	Extend wiringPi with the HTU21D I2C humidity and Temperature
+ *	sensor. This is used in the Pi Weather station.
+ *	Copyright (c) 2016 Gordon Henderson
+ ***********************************************************************
+ * This file is part of wiringPi:
+ *	https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ *    wiringPi is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as
+ *    published by the Free Software Foundation, either version 3 of the
+ *    License, or (at your option) any later version.
+ *
+ *    wiringPi is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public
+ *    License along with wiringPi.
+ *    If not, see <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#include <unistd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "wiringPi.h"
+#include "wiringPiI2C.h"
+
+#include "htu21d.h"
+
+#define	DEBUG
+#undef	FAKE_SENSOR
+
+#define	I2C_ADDRESS	0x40
+
+int checksum (UNU uint8_t data [4])
+{
+  return TRUE ;
+}
+
+
+
+/*
+ * myAnalogRead:
+ *********************************************************************************
+ */
+
+static int myAnalogRead (struct wiringPiNodeStruct *node, int pin)
+{
+  int chan = pin - node->pinBase ;
+  int fd   = node->fd ;
+  uint8_t data [4] ;
+  uint32_t sTemp, sHumid ;
+  double   fTemp, fHumid ;
+  int      cTemp, cHumid ;
+
+  /**/ if (chan == 0)	// Read Temperature
+  {
+
+// Send read temperature command:
+
+    data [0] = 0xF3 ;
+    if (write (fd, data, 1) != 1)
+      return -9999 ;
+
+// Wait then read the data
+
+    delay (50) ;
+    if (read (fd, data, 3) != 3)
+      return -9998 ;
+
+    if (!checksum (data))
+      return -9997 ;
+
+// Do the calculation
+
+    sTemp = (data [0] << 8) | data [1] ;
+    fTemp = -48.85 + 175.72 * (double)sTemp / 63356.0 ;
+    cTemp = (int)rint (((100.0 * fTemp) + 0.5) / 10.0) ;
+    return cTemp ;
+  }
+  else if (chan == 1)	// humidity
+  {
+// Send read humidity command:
+
+    data [0] = 0xF5 ;
+    if (write (fd, data, 1) != 1)
+      return -9999 ;
+
+// Wait then read the data
+
+    delay (50) ;
+    if (read (fd, data, 3) != 3)
+      return -9998 ;
+
+    if (!checksum (data))
+      return -9997 ;
+
+    sHumid = (data [0] << 8) | data [1] ;
+    fHumid = -6.0 + 125.0 * (double)sHumid / 65536.0 ;
+    cHumid = (int)rint (((100.0 * fHumid) + 0.5) / 10.0) ;
+    return cHumid ;
+  }
+  else
+    return -9999 ;
+}
+
+
+/*
+ * htu21dSetup:
+ *	Create a new instance of a HTU21D I2C GPIO interface.
+ *	This chip has a fixed I2C address, so we are not providing any
+ *	allowance to change this.
+ *********************************************************************************
+ */
+
+int htu21dSetup (const int pinBase)
+{
+  int fd ;
+  struct wiringPiNodeStruct *node ;
+  uint8_t data ;
+  int status ;
+
+  if ((fd = wiringPiI2CSetup (I2C_ADDRESS)) < 0)
+    return FALSE ;
+
+  node = wiringPiNewNode (pinBase, 2) ;
+
+  node->fd         = fd ;
+  node->analogRead = myAnalogRead ;
+
+// Send a reset code to it:
+
+  data = 0xFE ;
+  if (write (fd, &data, 1) != 1)
+    return FALSE ;
+
+  delay (15) ;
+
+// Read the status register to check it's really there
+
+  status = wiringPiI2CReadReg8 (fd, 0xE7) ;
+
+  return (status == 0x02) ? TRUE : FALSE ;
+}

+ 34 - 0
wiringPi/htu21d.h

@@ -0,0 +1,34 @@
+/*
+ * htu21d.h:
+ *	Extend wiringPi with the HTU21D I2C Humidity and Temperature
+ *	sensor.
+ *	Copyright (c) 2016 Gordon Henderson
+ ***********************************************************************
+ * This file is part of wiringPi:
+ *	https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ *    wiringPi is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as
+ *    published by the Free Software Foundation, either version 3 of the
+ *    License, or (at your option) any later version.
+ *
+ *    wiringPi is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public
+ *    License along with wiringPi.
+ *    If not, see <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int htu21dSetup (const int pinBase) ;
+
+#ifdef __cplusplus
+}
+#endif

+ 1 - 1
wiringPi/mcp3002.c

@@ -49,7 +49,7 @@ static int myAnalogRead (struct wiringPiNodeStruct *node, int pin)
 
   wiringPiSPIDataRW (node->fd, spiData, 2) ;
 
-  return ((spiData [0] << 7) | (spiData [1] >> 1)) & 0x3FF ;
+  return ((spiData [0] << 8) | (spiData [1] >> 1)) & 0x3FF ;
 }
 
 

+ 1 - 1
wiringPi/pcf8591.c

@@ -36,7 +36,7 @@
  *********************************************************************************
  */
 
-static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value)
+static void myAnalogWrite (struct wiringPiNodeStruct *node, UNU int pin, int value)
 {
   unsigned char b [2] ;
   b [0] = 0x40 ;

+ 95 - 0
wiringPi/pseudoPins.c

@@ -0,0 +1,95 @@
+/*
+ * pseudoPins.c:
+ *	Extend wiringPi with a number of pseudo pins which can be
+ *	digitally or analog written/read.
+ *
+ *	Note:
+ *		Just one set of pseudo pins can exist per Raspberry Pi.
+ *		These pins are shared between all programs running on
+ *		that Raspberry Pi. The values are also persistant as
+ *		they live in shared RAM. This gives you a means for
+ *		temporary variable storing/sharing between programs,
+ *		or for other cunning things I've not thought of yet..
+ *
+ *	Copyright (c) 2012-2016 Gordon Henderson
+ ***********************************************************************
+ * This file is part of wiringPi:
+ *	https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ *    wiringPi is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as
+ *    published by the Free Software Foundation, either version 3 of the
+ *    License, or (at your option) any later version.
+ *
+ *    wiringPi is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public
+ *    License along with wiringPi.
+ *    If not, see <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#define	SHARED_NAME	"wiringPiPseudoPins"
+#define	PSEUDO_PINS	64
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <wiringPi.h>
+
+#include "pseudoPins.h"
+
+static int myAnalogRead (struct wiringPiNodeStruct *node, int pin)
+{
+  int *ptr   = (int *)node->data0 ;
+  int  myPin = pin - node->pinBase ;
+
+  return *(ptr + myPin) ;
+}
+
+
+static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value)
+{
+  int *ptr   = (int *)node->data0 ;
+  int  myPin = pin - node->pinBase ;
+
+  *(ptr + myPin) = value ;
+}
+
+
+/*
+ * pseudoPinsSetup:
+ *	Create a new wiringPi device node for the pseudoPins driver
+ *********************************************************************************
+ */
+
+int pseudoPinsSetup (const int pinBase)
+{
+  struct wiringPiNodeStruct *node ;
+  void *ptr ;
+
+  node = wiringPiNewNode (pinBase, PSEUDO_PINS) ;
+
+  node->fd = shm_open (SHARED_NAME, O_CREAT | O_RDWR, 0666) ;
+
+  if (node->fd < 0)
+    return FALSE ;
+
+  if (ftruncate (node->fd, PSEUDO_PINS * sizeof (int)) < 0)
+    return FALSE ;
+
+  ptr = mmap (NULL, PSEUDO_PINS * sizeof (int), PROT_READ | PROT_WRITE, MAP_SHARED, node->fd, 0) ;
+
+  node->data0 = (unsigned int)ptr ;
+
+  node->analogRead  = myAnalogRead ;
+  node->analogWrite = myAnalogWrite ;
+
+  return TRUE ;
+}

+ 26 - 0
wiringPi/pseudoPins.h

@@ -0,0 +1,26 @@
+/*
+ * pseudoPins.h:
+ *	Extend wiringPi with a number of pseudo pins which can be
+ *	digitally or analog written/read.
+ *	Copyright (c) 2012-2016 Gordon Henderson
+ ***********************************************************************
+ * This file is part of wiringPi:
+ *	https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ *    wiringPi is free software: you can redistribute it and/or modify
+ *    it under the terms of the GNU Lesser General Public License as
+ *    published by the Free Software Foundation, either version 3 of the
+ *    License, or (at your option) any later version.
+ *
+ *    wiringPi is distributed in the hope that it will be useful,
+ *    but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *    GNU Lesser General Public License for more details.
+ *
+ *    You should have received a copy of the GNU Lesser General Public
+ *    License along with wiringPi.
+ *    If not, see <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+extern int pseudoPinsSetup (const int pinBase) ;

+ 13 - 3
wiringPi/softPwm.c

@@ -23,6 +23,7 @@
  */
 
 #include <stdio.h>
+#include <malloc.h>
 #include <pthread.h>
 
 #include "wiringPi.h"
@@ -63,7 +64,7 @@ static volatile int newPin = -1 ;
  *********************************************************************************
  */
 
-static PI_THREAD (softPwmThread)
+static void *softPwmThread (void *arg)
 {
   int pin, mark, space ;
   struct sched_param param ;
@@ -71,6 +72,9 @@ static PI_THREAD (softPwmThread)
   param.sched_priority = sched_get_priority_max (SCHED_RR) ;
   pthread_setschedparam (pthread_self (), SCHED_RR, &param) ;
 
+  pin = *((int *)arg) ;
+  free (arg) ;
+
   pin    = newPin ;
   newPin = -1 ;
 
@@ -123,11 +127,16 @@ int softPwmCreate (int pin, int initialValue, int pwmRange)
 {
   int res ;
   pthread_t myThread ;
+  int *passPin ;
 
   if (range [pin] != 0)	// Already running on this pin
     return -1 ;
 
-  if (range <= 0)
+  if (pwmRange <= 0)
+    return -1 ;
+
+  passPin = malloc (sizeof (*passPin)) ;
+  if (passPin == NULL)
     return -1 ;
 
   pinMode      (pin, OUTPUT) ;
@@ -136,8 +145,9 @@ int softPwmCreate (int pin, int initialValue, int pwmRange)
   marks [pin] = initialValue ;
   range [pin] = pwmRange ;
 
+  *passPin = pin ;
   newPin = pin ;
-  res    = pthread_create (&myThread, NULL, softPwmThread, NULL) ;
+  res    = pthread_create (&myThread, NULL, softPwmThread, (void *)passPin) ;
 
   while (newPin != -1)
     delay (1) ;

+ 242 - 206
wiringPi/wiringPi.c

@@ -1,7 +1,7 @@
 /*
  * wiringPi:
  *	Arduino look-a-like Wiring library for the Raspberry Pi
- *	Copyright (c) 2012-2015 Gordon Henderson
+ *	Copyright (c) 2012-2017 Gordon Henderson
  *	Additional code for pwmSetClock by Chris Hall <chris@kchall.plus.com>
  *
  *	Thanks to code samples from Gert Jan van Loo and the
@@ -75,6 +75,7 @@
 #include "softTone.h"
 
 #include "wiringPi.h"
+#include "../version.h"
 
 // Environment Variables
 
@@ -129,9 +130,8 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ;
 //	that I can find )-:
 //
 // Updates in September 2015 - all now static variables (and apologies for the caps)
-//	due to the Pi v2 and the new /dev/gpiomem interface
+//	due to the Pi v2, v3, etc. and the new /dev/gpiomem interface
 
-static volatile unsigned int RASPBERRY_PI_PERI_BASE ;
 static volatile unsigned int GPIO_PADS ;
 static volatile unsigned int GPIO_CLOCK_BASE ;
 static volatile unsigned int GPIO_BASE ;
@@ -197,13 +197,18 @@ static volatile uint32_t *timer ;
 static volatile uint32_t *timerIrqRaw ;
 #endif
 
-
 // Data for use with the boardId functions.
 //	The order of entries here to correspond with the PI_MODEL_X
 //	and PI_VERSION_X defines in wiringPi.h
 //	Only intended for the gpio command - use at your own risk!
 
-static int piModel2 = FALSE ;
+// piGpioBase:
+//	The base address of the GPIO memory mapped hardware IO
+
+#define	GPIO_PERI_BASE_OLD	0x20000000
+#define	GPIO_PERI_BASE_NEW	0x3F000000
+
+static volatile unsigned int piGpioBase = 0 ;
 
 const char *piModelNames [16] =
 {
@@ -217,7 +222,7 @@ const char *piModelNames [16] =
   "Unknown07",	// 07
   "Pi 3",	// 08
   "Pi Zero",	// 09
-  "Unknown10",	// 10
+  "CM3",	// 10
   "Unknown11",	// 11
   "Unknown12",	// 12
   "Unknown13",	// 13
@@ -649,7 +654,7 @@ int wiringPiFailure (int fatal, const char *message, ...)
 
 
 /*
- * piBoardRev:
+ * piGpioLayout:
  *	Return a number representing the hardware revision of the board.
  *	This is not strictly the board revision but is used to check the
  *	layout of the GPIO connector - and there are 2 types that we are
@@ -666,30 +671,34 @@ int wiringPiFailure (int fatal, const char *message, ...)
  *	3 GPIO pins on the (original) 26-way header - BCM_GPIO 22 was dropped and
  *	replaced with 27, and 0 + 1 - I2C bus 0 was changed to 2 + 3; I2C bus 1.
  *
+ *	Additionally, here we set the piModel2 flag too. This is again, nothing to
+ *	do with the actual model, but the major version numbers - the GPIO base
+ *	hardware address changed at model 2 and above (not the Zero though)
+ *
  *********************************************************************************
  */
 
-static void piBoardRevOops (const char *why)
+static void piGpioLayoutOops (const char *why)
 {
-  fprintf (stderr, "piBoardRev: Unable to determine board revision from /proc/cpuinfo\n") ;
+  fprintf (stderr, "Oops: Unable to determine board revision from /proc/cpuinfo\n") ;
   fprintf (stderr, " -> %s\n", why) ;
-  fprintf (stderr, " ->  You may want to check:\n") ;
-  fprintf (stderr, " ->  http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ;
+  fprintf (stderr, " ->  You'd best google the error to find out why.\n") ;
+//fprintf (stderr, " ->  http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ;
   exit (EXIT_FAILURE) ;
 }
 
-int piBoardRev (void)
+int piGpioLayout (void)
 {
   FILE *cpuFd ;
   char line [120] ;
   char *c ;
-  static int  boardRev = -1 ;
+  static int  gpioLayout = -1 ;
 
-  if (boardRev != -1)	// No point checking twice
-    return boardRev ;
+  if (gpioLayout != -1)	// No point checking twice
+    return gpioLayout ;
 
   if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL)
-    piBoardRevOops ("Unable to open /proc/cpuinfo") ;
+    piGpioLayoutOops ("Unable to open /proc/cpuinfo") ;
 
 // Start by looking for the Architecture to make sure we're really running
 //	on a Pi. I'm getting fed-up with people whinging at me because
@@ -700,23 +709,23 @@ int piBoardRev (void)
       break ;
 
   if (strncmp (line, "Hardware", 8) != 0)
-    piBoardRevOops ("No hardware line") ;
+    piGpioLayoutOops ("No \"Hardware\" line") ;
 
   if (wiringPiDebug)
-    printf ("piboardRev: Hardware: %s\n", line) ;
+    printf ("piGpioLayout: Hardware: %s\n", line) ;
 
-// See if it's BCM2708 or BCM2709
+// See if it's BCM2708 or BCM2709 or the new BCM2835.
 
-  if (strstr (line, "BCM2709") != NULL)	// Pi v2 - no point doing anything more at this point
-  {
-    piModel2 = TRUE ;
-    fclose (cpuFd) ;
-    return boardRev = 2 ;
-  }
-  else if (strstr (line, "BCM2708") == NULL)
+// OK. As of Kernel 4.8,  we have BCM2835 only, regardless of model.
+//	However I still want to check because it will trap the cheapskates and rip-
+//	off merchants who want to use wiringPi on non-Raspberry Pi platforms - which
+//	I do not support so don't email me your bleating whinges about anything
+//	other than a genuine Raspberry Pi.
+
+  if (! (strstr (line, "BCM2708") || strstr (line, "BCM2709") || strstr (line, "BCM2835")))
   {
     fprintf (stderr, "Unable to determine hardware version. I see: %s,\n", line) ;
-    fprintf (stderr, " - expecting BCM2708 or BCM2709.\n") ;
+    fprintf (stderr, " - expecting BCM2708, BCM2709 or BCM2835.\n") ;
     fprintf (stderr, "If this is a genuine Raspberry Pi then please report this\n") ;
     fprintf (stderr, "to projects@drogon.net. If this is not a Raspberry Pi then you\n") ;
     fprintf (stderr, "are on your own as wiringPi is designed to support the\n") ;
@@ -724,8 +733,11 @@ int piBoardRev (void)
     exit (EXIT_FAILURE) ;
   }
 
-// Now do the rest of it as before - we just need to see if it's an older
-//	Rev 1 as anything else is rev 2.
+// Right - we're Probably on a Raspberry Pi. Check the revision field for the real
+//	hardware type
+//	In-future, I ought to use the device tree as there are now Pi entries in
+//	/proc/device-tree/ ...
+//	but I'll leave that for the next revision.
 
 // Isolate the Revision line
 
@@ -737,7 +749,7 @@ int piBoardRev (void)
   fclose (cpuFd) ;
 
   if (strncmp (line, "Revision", 8) != 0)
-    piBoardRevOops ("No \"Revision\" line") ;
+    piGpioLayoutOops ("No \"Revision\" line") ;
 
 // Chomp trailing CR/NL
 
@@ -745,7 +757,7 @@ int piBoardRev (void)
     *c = 0 ;
   
   if (wiringPiDebug)
-    printf ("piboardRev: Revision string: %s\n", line) ;
+    printf ("piGpioLayout: Revision string: %s\n", line) ;
 
 // Scan to the first character of the revision number
 
@@ -754,7 +766,7 @@ int piBoardRev (void)
       break ;
 
   if (*c != ':')
-    piBoardRevOops ("Bogus \"Revision\" line (no colon)") ;
+    piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ;
 
 // Chomp spaces
 
@@ -763,47 +775,44 @@ int piBoardRev (void)
     ++c ;
 
   if (!isxdigit (*c))
-    piBoardRevOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ;
+    piGpioLayoutOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ;
 
 // Make sure its long enough
 
   if (strlen (c) < 4)
-    piBoardRevOops ("Bogus revision line (too small)") ;
-
-// If you have overvolted the Pi, then it appears that the revision
-//	has 100000 added to it!
-// The actual condition for it being set is:
-//	 (force_turbo || current_limit_override || temp_limit>85) && over_voltage>0
-
-
-// This test is not correct for the new encoding scheme, so we'll remove it here as
-//	we don't really need it at this point.
-
-/********************
-  if (wiringPiDebug)
-    if (strlen (c) != 4)
-      printf ("piboardRev: This Pi has/is (force_turbo || current_limit_override || temp_limit>85) && over_voltage>0\n") ;
-*******************/
+    piGpioLayoutOops ("Bogus revision line (too small)") ;
 
-// Isolate  last 4 characters:
+// Isolate  last 4 characters: (in-case of overvolting or new encoding scheme)
 
   c = c + strlen (c) - 4 ;
 
   if (wiringPiDebug)
-    printf ("piboardRev: last4Chars are: \"%s\"\n", c) ;
+    printf ("piGpioLayout: last4Chars are: \"%s\"\n", c) ;
 
   if ( (strcmp (c, "0002") == 0) || (strcmp (c, "0003") == 0))
-    boardRev = 1 ;
+    gpioLayout = 1 ;
   else
-    boardRev = 2 ;	// Covers everything else from the B revision 2 to the B+, the Pi v2 and CM's.
+    gpioLayout = 2 ;	// Covers everything else from the B revision 2 to the B+, the Pi v2, v3, zero and CM's.
 
   if (wiringPiDebug)
-    printf ("piBoardRev: Returning revision: %d\n", boardRev) ;
+    printf ("piGpioLayoutOops: Returning revision: %d\n", gpioLayout) ;
 
-  return boardRev ;
+  return gpioLayout ;
+}
+
+/*
+ * piBoardRev:
+ *	Deprecated, but does the same as piGpioLayout
+ *********************************************************************************
+ */
+
+int piBoardRev (void)
+{
+  return piGpioLayout () ;
 }
 
 
+
 /*
  * piBoardId:
  *	Return the real details of the board we have.
@@ -822,20 +831,32 @@ int piBoardRev (void)
  *		0003 - Model B,  Rev 1.1, 256MB, Egoman, Fuses/D14 removed.
  *
  *	Newer Pi's with remapped GPIO:
- *		0004 - Model B,  Rev 2,   256MB, Sony
- *		0005 - Model B,  Rev 2,   256MB, Qisda
- *		0006 - Model B,  Rev 2,   256MB, Egoman
- *		0007 - Model A,  Rev 2,   256MB, Egoman
- *		0008 - Model A,  Rev 2,   256MB, Sony
- *		0009 - Model A,  Rev 2,   256MB, Qisda
- *		000d - Model B,  Rev 2,   512MB, Egoman	(Red Pi, Blue Pi?)
- *		000e - Model B,  Rev 2,   512MB, Sony
- *		000f - Model B,  Rev 2,   512MB, Qisda
+ *		0004 - Model B,  Rev 1.2, 256MB, Sony
+ *		0005 - Model B,  Rev 1.2, 256MB, Egoman
+ *		0006 - Model B,  Rev 1.2, 256MB, Egoman
+ *
+ *		0007 - Model A,  Rev 1.2, 256MB, Egoman
+ *		0008 - Model A,  Rev 1.2, 256MB, Sony
+ *		0009 - Model A,  Rev 1.2, 256MB, Egoman
+ *
+ *		000d - Model B,  Rev 1.2, 512MB, Egoman	(Red Pi, Blue Pi?)
+ *		000e - Model B,  Rev 1.2, 512MB, Sony
+ *		000f - Model B,  Rev 1.2, 512MB, Egoman
+ *
  *		0010 - Model B+, Rev 1.2, 512MB, Sony
- *		0011 - Pi CM,    Rev 1.2, 512MB, Sony
- *		0012 - Model A+  Rev 1.2, 256MB, Sony
- *		0014 - Pi CM,    Rev 1.1, 512MB, Sony (Actual Revision might be different)
- *		0015 - Model A+  Rev 1.1, 256MB, Sony
+ *		0013 - Model B+  Rev 1.2, 512MB, Embest
+ *		0016 - Model B+  Rev 1.2, 512MB, Sony
+ *		0019 - Model B+  Rev 1.2, 512MB, Egoman
+ *
+ *		0011 - Pi CM,    Rev 1.1, 512MB, Sony
+ *		0014 - Pi CM,    Rev 1.1, 512MB, Embest
+ *		0017 - Pi CM,    Rev 1.1, 512MB, Sony
+ *		001a - Pi CM,    Rev 1.1, 512MB, Egoman
+ *
+ *		0012 - Model A+  Rev 1.1, 256MB, Sony
+ *		0015 - Model A+  Rev 1.1, 512MB, Embest
+ *		0018 - Model A+  Rev 1.1, 256MB, Sony
+ *		001b - Model A+  Rev 1.1, 256MB, Egoman
  *
  *	A small thorn is the olde style overvolting - that will add in
  *		1000000
@@ -870,10 +891,10 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty)
 //	Will deal with the properly later on - for now, lets just get it going...
 //  unsigned int modelNum ;
 
-  (void)piBoardRev () ;	// Call this first to make sure all's OK. Don't care about the result.
+  (void)piGpioLayout () ;	// Call this first to make sure all's OK. Don't care about the result.
 
   if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL)
-    piBoardRevOops ("Unable to open /proc/cpuinfo") ;
+    piGpioLayoutOops ("Unable to open /proc/cpuinfo") ;
 
   while (fgets (line, 120, cpuFd) != NULL)
     if (strncmp (line, "Revision", 8) == 0)
@@ -882,7 +903,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty)
   fclose (cpuFd) ;
 
   if (strncmp (line, "Revision", 8) != 0)
-    piBoardRevOops ("No \"Revision\" line") ;
+    piGpioLayoutOops ("No \"Revision\" line") ;
 
 // Chomp trailing CR/NL
 
@@ -901,7 +922,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty)
       break ;
 
   if (*c != ':')
-    piBoardRevOops ("Bogus \"Revision\" line (no colon)") ;
+    piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ;
 
 // Chomp spaces
 
@@ -910,7 +931,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty)
     ++c ;
 
   if (!isxdigit (*c))
-    piBoardRevOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ;
+    piGpioLayoutOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ;
 
   revision = (unsigned int)strtol (c, NULL, 16) ; // Hex number with no leading 0x
 
@@ -935,7 +956,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty)
     *warranty = bWarranty ;
 
     if (wiringPiDebug)
-      printf ("piboardId: rev: %d, type: %d, proc: %d, mfg: %d, mem: %d, warranty: %d\n",
+      printf ("piBoardId: rev: %d, type: %d, proc: %d, mfg: %d, mem: %d, warranty: %d\n",
 		bRev, bType, bProc, bMfg, bMem, bWarranty) ;
   }
   else					// Old way
@@ -944,12 +965,12 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty)
       printf ("piBoardId: Old Way: revision is: %s\n", c) ;
 
     if (!isdigit (*c))
-      piBoardRevOops ("Bogus \"Revision\" line (no digit at start of revision)") ;
+      piGpioLayoutOops ("Bogus \"Revision\" line (no digit at start of revision)") ;
 
 // Make sure its long enough
 
     if (strlen (c) < 4)
-      piBoardRevOops ("Bogus \"Revision\" line (not long enough)") ;
+      piGpioLayoutOops ("Bogus \"Revision\" line (not long enough)") ;
 
 // If longer than 4, we'll assume it's been overvolted
 
@@ -963,21 +984,34 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty)
 
     /**/ if (strcmp (c, "0002") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_1   ; *mem = 0 ; *maker = PI_MAKER_EGOMAN  ; }
     else if (strcmp (c, "0003") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN  ; }
-    else if (strcmp (c, "0004") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_2   ; *mem = 0 ; *maker = PI_MAKER_SONY    ; }
-    else if (strcmp (c, "0005") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_2   ; *mem = 0 ; *maker = PI_MAKER_UNKNOWN ; }
-    else if (strcmp (c, "0006") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_2   ; *mem = 0 ; *maker = PI_MAKER_EGOMAN  ; }
-    else if (strcmp (c, "0007") == 0) { *model = PI_MODEL_A  ; *rev = PI_VERSION_2   ; *mem = 0 ; *maker = PI_MAKER_EGOMAN  ; }
-    else if (strcmp (c, "0008") == 0) { *model = PI_MODEL_A  ; *rev = PI_VERSION_2   ; *mem = 0 ; *maker = PI_MAKER_SONY ;  ; }
-    else if (strcmp (c, "0009") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_2   ; *mem = 0 ; *maker = PI_MAKER_UNKNOWN ; }
-    else if (strcmp (c, "000d") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_2   ; *mem = 1 ; *maker = PI_MAKER_EGOMAN  ; }
-    else if (strcmp (c, "000e") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_2   ; *mem = 1 ; *maker = PI_MAKER_SONY    ; }
-    else if (strcmp (c, "000f") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_2   ; *mem = 1 ; *maker = PI_MAKER_EGOMAN  ; }
+
+    else if (strcmp (c, "0004") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY    ; }
+    else if (strcmp (c, "0005") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN  ; }
+    else if (strcmp (c, "0006") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN  ; }
+
+    else if (strcmp (c, "0007") == 0) { *model = PI_MODEL_A  ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN  ; }
+    else if (strcmp (c, "0008") == 0) { *model = PI_MODEL_A  ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ;  ; }
+    else if (strcmp (c, "0009") == 0) { *model = PI_MODEL_A  ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN  ; }
+
+    else if (strcmp (c, "000d") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN  ; }
+    else if (strcmp (c, "000e") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY    ; }
+    else if (strcmp (c, "000f") == 0) { *model = PI_MODEL_B  ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN  ; }
+
     else if (strcmp (c, "0010") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY    ; }
-    else if (strcmp (c, "0011") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY    ; }
-    else if (strcmp (c, "0012") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY    ; }
-    else if (strcmp (c, "0013") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN  ; }
-    else if (strcmp (c, "0014") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY    ; }
-    else if (strcmp (c, "0015") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY    ; }
+    else if (strcmp (c, "0013") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EMBEST  ; }
+    else if (strcmp (c, "0016") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY    ; }
+    else if (strcmp (c, "0019") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN  ; }
+
+    else if (strcmp (c, "0011") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_SONY    ; }
+    else if (strcmp (c, "0014") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EMBEST  ; }
+    else if (strcmp (c, "0017") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_SONY    ; }
+    else if (strcmp (c, "001a") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN  ; }
+
+    else if (strcmp (c, "0012") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY    ; }
+    else if (strcmp (c, "0015") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EMBEST  ; }
+    else if (strcmp (c, "0018") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY    ; }
+    else if (strcmp (c, "001b") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN  ; }
+
     else                              { *model = 0           ; *rev = 0              ; *mem =   0 ; *maker = 0 ;               }
   }
 }
@@ -1022,9 +1056,6 @@ void setPadDrive (int group, int value)
 
   if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO))
   {
-    if (RASPBERRY_PI_PERI_BASE == 0)	// Ignore for now
-      return ;
-
     if ((group < 0) || (group > 2))
       return ;
 
@@ -1098,9 +1129,6 @@ void pwmSetRange (unsigned int range)
 {
   if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO))
   {
-    if (RASPBERRY_PI_PERI_BASE == 0)	// Ignore for now
-      return ;
-
     *(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ;
     *(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ;
   }
@@ -1122,9 +1150,6 @@ void pwmSetClock (int divisor)
 
   if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO))
   {
-    if (RASPBERRY_PI_PERI_BASE == 0)	// Ignore for now
-      return ;
-
     if (wiringPiDebug)
       printf ("Setting to: %d. Current: 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ;
 
@@ -1177,9 +1202,6 @@ void gpioClockSet (int pin, int freq)
   else if (wiringPiMode != WPI_MODE_GPIO)
     return ;
   
-  if (RASPBERRY_PI_PERI_BASE == 0)	// Ignore for now
-    return ;
-
   divi = 19200000 / freq ;
   divr = 19200000 % freq ;
   divf = (int)((double)divr * 4096.0 / 19200000.0) ;
@@ -1222,13 +1244,13 @@ struct wiringPiNodeStruct *wiringPiFindNode (int pin)
  *********************************************************************************
  */
 
-static void pinModeDummy             (struct wiringPiNodeStruct *node, int pin, int mode)  { return ; }
-static void pullUpDnControlDummy     (struct wiringPiNodeStruct *node, int pin, int pud)   { return ; }
-static int  digitalReadDummy         (struct wiringPiNodeStruct *node, int pin)            { return LOW ; }
-static void digitalWriteDummy        (struct wiringPiNodeStruct *node, int pin, int value) { return ; }
-static void pwmWriteDummy            (struct wiringPiNodeStruct *node, int pin, int value) { return ; }
-static int  analogReadDummy          (struct wiringPiNodeStruct *node, int pin)            { return 0 ; }
-static void analogWriteDummy         (struct wiringPiNodeStruct *node, int pin, int value) { return ; }
+static void pinModeDummy             (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int mode)  { return ; }
+static void pullUpDnControlDummy     (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int pud)   { return ; }
+static int  digitalReadDummy         (UNU struct wiringPiNodeStruct *node, UNU int UNU pin)            { return LOW ; }
+static void digitalWriteDummy        (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; }
+static void pwmWriteDummy            (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; }
+static int  analogReadDummy          (UNU struct wiringPiNodeStruct *node, UNU int pin)            { return 0 ; }
+static void analogWriteDummy         (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; }
 
 struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins)
 {
@@ -1352,17 +1374,11 @@ void pinMode (int pin, int mode)
       softToneCreate (origPin) ;
     else if (mode == PWM_TONE_OUTPUT)
     {
-      if (RASPBERRY_PI_PERI_BASE == 0)	// Ignore for now
-	return ;
-
       pinMode (origPin, PWM_OUTPUT) ;	// Call myself to enable PWM mode
       pwmSetMode (PWM_MODE_MS) ;
     }
     else if (mode == PWM_OUTPUT)
     {
-      if (RASPBERRY_PI_PERI_BASE == 0)	// Ignore for now
-	return ;
-
       if ((alt = gpioToPwmALT [pin]) == 0)	// Not a hardware capable PWM pin
 	return ;
 
@@ -1377,9 +1393,6 @@ void pinMode (int pin, int mode)
     }
     else if (mode == GPIO_CLOCK)
     {
-      if (RASPBERRY_PI_PERI_BASE == 0)	// Ignore for now
-	return ;
-
       if ((alt = gpioToGpClkALT0 [pin]) == 0)	// Not a GPIO_CLOCK pin
 	return ;
 
@@ -1534,9 +1547,6 @@ void pwmWrite (int pin, int value)
 
   if ((pin & PI_GPIO_MASK) == 0)		// On-Board Pin
   {
-    if (RASPBERRY_PI_PERI_BASE == 0)	// Ignore for now
-      return ;
-
     /**/ if (wiringPiMode == WPI_MODE_PINS)
       pin = pinToGpio [pin] ;
     else if (wiringPiMode == WPI_MODE_PHYS)
@@ -1603,9 +1613,6 @@ void pwmToneWrite (int pin, int freq)
 {
   int range ;
 
-  if (RASPBERRY_PI_PERI_BASE == 0)	// Ignore for now
-    return ;
-
   if (freq == 0)
     pwmWrite (pin, 0) ;             // Off
   else
@@ -1630,7 +1637,7 @@ void pwmToneWrite (int pin, int freq)
  *	Reading is just bit fiddling.
  *	These are wiringPi pin numbers 0..7, or BCM_GPIO pin numbers
  *	17, 18, 22, 23, 24, 24, 4 on a Pi v1 rev 0-3
- *	17, 18, 27, 23, 24, 24, 4 on a Pi v1 rev 3 onwards or B+, 2, zero
+ *	17, 18, 27, 23, 24, 24, 4 on a Pi v1 rev 3 onwards or B+, 2, 3, zero
  *********************************************************************************
  */
 
@@ -1720,8 +1727,8 @@ void digitalWriteByte2 (const int value)
   }
   else
   {
-    *(gpio + gpioToGPCLR [0]) = 0x0FF00000 ;
-    *(gpio + gpioToGPSET [0]) = (value & 0xFF) << 20 ;
+    *(gpio + gpioToGPCLR [0]) = (~value & 0xFF) << 20 ; // 0x0FF00000; ILJ > CHANGE: Old causes glitch
+    *(gpio + gpioToGPSET [0]) = ( value & 0xFF) << 20 ;
   }
 }
 
@@ -1772,18 +1779,20 @@ int waitForInterrupt (int pin, int mS)
 // Setup poll structure
 
   polls.fd     = fd ;
-  polls.events = POLLPRI ;	// Urgent data!
+  polls.events = POLLPRI | POLLERR ;
 
 // Wait for it ...
 
   x = poll (&polls, 1, mS) ;
 
-// Do a dummy read to clear the interrupt
+// If no error, do a dummy read to clear the interrupt
 //	A one character read appars to be enough.
-//	Followed by a seek to reset it.
 
-  (void)read (fd, &c, 1) ;
-  lseek (fd, 0, SEEK_SET) ;
+  if (x > 0)
+  {
+    lseek (fd, 0, SEEK_SET) ;	// Rewind
+    (void)read (fd, &c, 1) ;	// Read & clear
+  }
 
   return x ;
 }
@@ -1797,7 +1806,7 @@ int waitForInterrupt (int pin, int mS)
  *********************************************************************************
  */
 
-static void *interruptHandler (void *arg)
+static void *interruptHandler (UNU void *arg)
 {
   int myPin ;
 
@@ -1922,11 +1931,19 @@ int wiringPiISR (int pin, int mode, void (*function)(void))
 
 static void initialiseEpoch (void)
 {
+#ifdef	OLD_WAY
   struct timeval tv ;
 
   gettimeofday (&tv, NULL) ;
   epochMilli = (uint64_t)tv.tv_sec * (uint64_t)1000    + (uint64_t)(tv.tv_usec / 1000) ;
   epochMicro = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)(tv.tv_usec) ;
+#else
+  struct timespec ts ;
+
+  clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ;
+  epochMilli = (uint64_t)ts.tv_sec * (uint64_t)1000    + (uint64_t)(ts.tv_nsec / 1000000L) ;
+  epochMicro = (uint64_t)ts.tv_sec * (uint64_t)1000000 + (uint64_t)(ts.tv_nsec /    1000L) ;
+#endif
 }
 
 
@@ -2000,17 +2017,27 @@ void delayMicroseconds (unsigned int howLong)
 /*
  * millis:
  *	Return a number of milliseconds as an unsigned int.
+ *	Wraps at 49 days.
  *********************************************************************************
  */
 
 unsigned int millis (void)
 {
-  struct timeval tv ;
   uint64_t now ;
 
+#ifdef	OLD_WAY
+  struct timeval tv ;
+
   gettimeofday (&tv, NULL) ;
   now  = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ;
 
+#else
+  struct  timespec ts ;
+
+  clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ;
+  now  = (uint64_t)ts.tv_sec * (uint64_t)1000 + (uint64_t)(ts.tv_nsec / 1000000L) ;
+#endif
+
   return (uint32_t)(now - epochMilli) ;
 }
 
@@ -2018,20 +2045,41 @@ unsigned int millis (void)
 /*
  * micros:
  *	Return a number of microseconds as an unsigned int.
+ *	Wraps after 71 minutes.
  *********************************************************************************
  */
 
 unsigned int micros (void)
 {
-  struct timeval tv ;
   uint64_t now ;
+#ifdef	OLD_WAY
+  struct timeval tv ;
 
   gettimeofday (&tv, NULL) ;
   now  = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)tv.tv_usec ;
+#else
+  struct  timespec ts ;
+
+  clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ;
+  now  = (uint64_t)ts.tv_sec * (uint64_t)1000000 + (uint64_t)(ts.tv_nsec / 1000) ;
+#endif
+
 
   return (uint32_t)(now - epochMicro) ;
 }
 
+/*
+ * wiringPiVersion:
+ *	Return our current version number
+ *********************************************************************************
+ */
+
+void wiringPiVersion (int *major, int *minor)
+{
+  *major = VERSION_MAJOR ;
+  *minor = VERSION_MINOR ;
+}
+
 
 /*
  * wiringPiSetup:
@@ -2047,18 +2095,17 @@ unsigned int micros (void)
 int wiringPiSetup (void)
 {
   int   fd ;
-  int   boardRev ;
   int   model, rev, mem, maker, overVolted ;
-  static int alreadyCalled = FALSE ;
-
-// This is here to trap the unwary - those who's program appears to work then fails some
-//	time later with a weird error message because you run out of file-handles.
+  static int alreadyDoneThis = FALSE ;
 
-  if (alreadyCalled)
-    (void)wiringPiFailure (WPI_FATAL, "wiringPiSetup*: You must only call this once per program run. This is a fatal error. Please fix your code.\n") ;
+// It's actually a fatal error to call any of the wiringPiSetup routines more than once,
+//	(you run out of file handles!) but I'm fed-up with the useless twats who email
+//	me bleating that there is a bug in my code, so screw-em.
 
-  alreadyCalled = TRUE ;
+  if (alreadyDoneThis)
+    return 0 ;
 
+  alreadyDoneThis = TRUE ;
 
   if (getenv (ENV_DEBUG) != NULL)
     wiringPiDebug = TRUE ;
@@ -2066,101 +2113,99 @@ int wiringPiSetup (void)
   if (getenv (ENV_CODES) != NULL)
     wiringPiReturnCodes = TRUE ;
 
-  if (getenv (ENV_GPIOMEM) != NULL)
-    wiringPiTryGpioMem = TRUE ;
-
   if (wiringPiDebug)
-  {
     printf ("wiringPi: wiringPiSetup called\n") ;
-    if (wiringPiTryGpioMem)
-      printf ("wiringPi: Using /dev/gpiomem\n") ;
-  }
 
-  boardRev = piBoardRev () ;
+// Get the board ID information. We're not really using the information here,
+//	but it will give us information like the GPIO layout scheme (2 variants
+//	on the older 26-pin Pi's) and the GPIO peripheral base address.
+//	and if we're running on a compute module, then wiringPi pin numbers
+//	don't really many anything, so force native BCM mode anyway.
 
-  /**/ if (boardRev == 1)	// A, B, Rev 1, 1.1
+  piBoardId (&model, &rev, &mem, &maker, &overVolted) ;
+
+  if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3))
+    wiringPiMode = WPI_MODE_GPIO ;
+  else
+    wiringPiMode = WPI_MODE_PINS ;
+
+  /**/ if (piGpioLayout () == 1)	// A, B, Rev 1, 1.1
   {
      pinToGpio =  pinToGpioR1 ;
     physToGpio = physToGpioR1 ;
   }
-  else 				// A, B, Rev 2, B+, CM, Pi2, Zero
+  else 					// A2, B2, A+, B+, CM, Pi2, Pi3, Zero
   {
      pinToGpio =  pinToGpioR2 ;
     physToGpio = physToGpioR2 ;
   }
 
-// Note that a Zero is a model 1
-
-  if (piModel2)
-    RASPBERRY_PI_PERI_BASE = 0x3F000000 ;
-  else
-    RASPBERRY_PI_PERI_BASE = 0x20000000 ;
-
-// Open the master /dev/ memory control device
-
-//	See if /dev/gpiomem exists and we can open it...
+// ...
 
-  if (wiringPiTryGpioMem)
+  switch (model)
   {
-    if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0)
-      return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/gpiomem: %s\n", strerror (errno)) ;
-    RASPBERRY_PI_PERI_BASE = 0 ;
+    case PI_MODEL_A:  case PI_MODEL_B:
+    case PI_MODEL_AP: case PI_MODEL_BP:
+    case PI_ALPHA:    case PI_MODEL_CM: case PI_MODEL_ZERO:
+      piGpioBase = GPIO_PERI_BASE_OLD ;
+      break ;
+
+    default:
+      piGpioBase = GPIO_PERI_BASE_NEW ;
+      break ;
   }
 
-//	... otherwise fall back to the original /dev/mem which requires root level access
+// Open the master /dev/ memory control device
+// Device strategy: December 2016:
+//	Try /dev/mem. If that fails, then 
+//	try /dev/gpiomem. If that fails then game over.
 
-  else
+  if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0)
   {
-
-//	This check is here because people are too stupid to check for themselves or read
-//		error messages.
-
-    if (geteuid () != 0)
-      (void)wiringPiFailure (WPI_FATAL, "wiringPiSetup: Must be root. (Did you forget sudo?)\n") ;
-
-    if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0)
-      return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ;
+    if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0)
+      return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem or /dev/gpiomem: %s.\n  Try running with sudo?\n", strerror (errno)) ;
+    piGpioBase = 0 ;
   }
 
 // Set the offsets into the memory interface.
 
-  GPIO_PADS 	  = RASPBERRY_PI_PERI_BASE + 0x00100000 ;
-  GPIO_CLOCK_BASE = RASPBERRY_PI_PERI_BASE + 0x00101000 ;
-  GPIO_BASE	  = RASPBERRY_PI_PERI_BASE + 0x00200000 ;
-  GPIO_TIMER	  = RASPBERRY_PI_PERI_BASE + 0x0000B000 ;
-  GPIO_PWM	  = RASPBERRY_PI_PERI_BASE + 0x0020C000 ;
+  GPIO_PADS 	  = piGpioBase + 0x00100000 ;
+  GPIO_CLOCK_BASE = piGpioBase + 0x00101000 ;
+  GPIO_BASE	  = piGpioBase + 0x00200000 ;
+  GPIO_TIMER	  = piGpioBase + 0x0000B000 ;
+  GPIO_PWM	  = piGpioBase + 0x0020C000 ;
 
 // Map the individual hardware components
 
 //	GPIO:
 
   gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ;
-  if ((int32_t)gpio == -1)
+  if (gpio == MAP_FAILED)
     return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ;
 
 //	PWM
 
   pwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PWM) ;
-  if ((int32_t)pwm == -1)
+  if (pwm == MAP_FAILED)
     return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PWM) failed: %s\n", strerror (errno)) ;
  
 //	Clock control (needed for PWM)
 
   clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_BASE) ;
-  if ((int32_t)clk == -1)
+  if (clk == MAP_FAILED)
     return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ;
  
 //	The drive pads
 
   pads = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PADS) ;
-  if ((int32_t)pads == -1)
+  if (pads == MAP_FAILED)
     return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PADS) failed: %s\n", strerror (errno)) ;
 
 #ifdef	USE_TIMER
 //	The system timer
 
   timer = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_TIMER) ;
-  if ((int32_t)timer == -1)
+  if (timer == MAP_FAILED)
     return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (TIMER) failed: %s\n", strerror (errno)) ;
 
 // Set the timer to free-running, 1MHz.
@@ -2174,14 +2219,6 @@ int wiringPiSetup (void)
 
   initialiseEpoch () ;
 
-// If we're running on a compute module, then wiringPi pin numbers don't really many anything...
-
-  piBoardId (&model, &rev, &mem, &maker, &overVolted) ;
-  if (model == PI_MODEL_CM)
-    wiringPiMode = WPI_MODE_GPIO ;
-  else
-    wiringPiMode = WPI_MODE_PINS ;
-
   return 0 ;
 }
 
@@ -2241,18 +2278,19 @@ int wiringPiSetupPhys (void)
 
 int wiringPiSetupSys (void)
 {
-  int boardRev ;
   int pin ;
   char fName [128] ;
-  static int alreadyCalled = FALSE ;
 
-// This is here to trap the unwary - those who's program appears to work then fails some
-//	time later with a weird error message because you run out of file-handles.
+  static int alreadyDoneThis = FALSE ;
 
-  if (alreadyCalled)
-    (void)wiringPiFailure (WPI_FATAL, "wiringPiSetupSys: You must only call this once per program run. This is a fatal error. Please fix your code.\n") ;
+// It's actually a fatal error to call any of the wiringPiSetup routines more than once,
+//	(you run out of file handles!) but I'm fed-up with the useless twats who email
+//	me bleating that there is a bug in my code, so screw-em.
 
-  alreadyCalled = TRUE ;
+  if (alreadyDoneThis)
+    return 0 ;
+
+  alreadyDoneThis = TRUE ;
 
   if (getenv (ENV_DEBUG) != NULL)
     wiringPiDebug = TRUE ;
@@ -2263,9 +2301,7 @@ int wiringPiSetupSys (void)
   if (wiringPiDebug)
     printf ("wiringPi: wiringPiSetupSys called\n") ;
 
-  boardRev = piBoardRev () ;
-
-  if (boardRev == 1)
+  if (piGpioLayout () == 1)
   {
      pinToGpio =  pinToGpioR1 ;
     physToGpio = physToGpioR1 ;

+ 21 - 14
wiringPi/wiringPi.h

@@ -1,7 +1,7 @@
 /*
  * wiringPi.h:
  *	Arduino like Wiring library for the Raspberry Pi.
- *	Copyright (c) 2012-2016 Gordon Henderson
+ *	Copyright (c) 2012-2017 Gordon Henderson
  ***********************************************************************
  * This file is part of wiringPi:
  *	https://projects.drogon.net/raspberry-pi/wiringpi/
@@ -32,6 +32,10 @@
 #  define	FALSE	(!TRUE)
 #endif
 
+// GCC warning suppressor
+
+#define	UNU	__attribute__((unused))
+
 // Handy defines
 
 // wiringPi modes
@@ -77,16 +81,17 @@
 // Pi model types and version numbers
 //	Intended for the GPIO program Use at your own risk.
 
-#define	PI_MODEL_A		0
-#define	PI_MODEL_B		1
-#define	PI_MODEL_AP		2
-#define	PI_MODEL_BP		3
-#define	PI_MODEL_2		4
-#define	PI_ALPHA		5
-#define	PI_MODEL_CM		6
-#define	PI_MODEL_07		7
-#define	PI_MODEL_3		8
-#define	PI_MODEL_ZERO		9
+#define	PI_MODEL_A		 0
+#define	PI_MODEL_B		 1
+#define	PI_MODEL_AP		 2
+#define	PI_MODEL_BP		 3
+#define	PI_MODEL_2		 4
+#define	PI_ALPHA		 5
+#define	PI_MODEL_CM		 6
+#define	PI_MODEL_07		 7
+#define	PI_MODEL_3		 8
+#define	PI_MODEL_ZERO		 9
+#define	PI_MODEL_CM3		10
 
 #define	PI_VERSION_1		0
 #define	PI_VERSION_1_1		1
@@ -95,7 +100,7 @@
 
 #define	PI_MAKER_SONY		0
 #define	PI_MAKER_EGOMAN		1
-#define	PI_MAKER_MBEST		2
+#define	PI_MAKER_EMBEST		2
 #define	PI_MAKER_UNKNOWN	3
 
 extern const char *piModelNames    [16] ;
@@ -108,7 +113,7 @@ extern const int   piMemorySize    [ 8] ;
 
 // Threads
 
-#define	PI_THREAD(X)	void *X (void *dummy)
+#define	PI_THREAD(X)	void *X (UNU void *dummy)
 
 // Failure modes
 
@@ -168,6 +173,7 @@ extern int wiringPiFailure (int fatal, const char *message, ...) ;
 extern struct wiringPiNodeStruct *wiringPiFindNode (int pin) ;
 extern struct wiringPiNodeStruct *wiringPiNewNode  (int pinBase, int numPins) ;
 
+extern void wiringPiVersion	(int *major, int *minor) ;
 extern int  wiringPiSetup       (void) ;
 extern int  wiringPiSetupSys    (void) ;
 extern int  wiringPiSetupGpio   (void) ;
@@ -190,7 +196,8 @@ extern int  wiringPiSetupPiFaceForGpioProg (void) ;	// Don't use this - for gpio
 
 // On-Board Raspberry Pi hardware specific stuff
 
-extern          int  piBoardRev          (void) ;
+extern          int  piGpioLayout        (void) ;
+extern          int  piBoardRev          (void) ;	// Deprecated
 extern          void piBoardId           (int *model, int *rev, int *mem, int *maker, int *overVolted) ;
 extern          int  wpiPinToGpio        (int wpiPin) ;
 extern          int  physPinToGpio       (int physPin) ;

+ 2 - 1
wiringPi/wiringPiI2C.c

@@ -52,6 +52,7 @@
 #include <string.h>
 #include <fcntl.h>
 #include <sys/ioctl.h>
+#include <asm/ioctl.h>
 
 #include "wiringPi.h"
 #include "wiringPiI2C.h"
@@ -221,7 +222,7 @@ int wiringPiI2CSetup (const int devId)
   int rev ;
   const char *device ;
 
-  rev = piBoardRev () ;
+  rev = piGpioLayout () ;
 
   if (rev == 1)
     device = "/dev/i2c-0" ;

+ 5 - 4
wiringPi/wiringPiSPI.c

@@ -28,6 +28,7 @@
 #include <errno.h>
 #include <string.h>
 #include <sys/ioctl.h>
+#include <asm/ioctl.h>
 #include <linux/spi/spidev.h>
 
 #include "wiringPi.h"
@@ -38,10 +39,10 @@
 // The SPI bus parameters
 //	Variables as they need to be passed as pointers later on
 
-const static char       *spiDev0  = "/dev/spidev0.0" ;
-const static char       *spiDev1  = "/dev/spidev0.1" ;
-const static uint8_t     spiBPW   = 8 ;
-const static uint16_t    spiDelay = 0 ;
+static const char       *spiDev0  = "/dev/spidev0.0" ;
+static const char       *spiDev1  = "/dev/spidev0.1" ;
+static const uint8_t     spiBPW   = 8 ;
+static const uint16_t    spiDelay = 0 ;
 
 static uint32_t    spiSpeeds [2] ;
 static int         spiFds [2] ;

+ 31 - 19
wiringPi/wiringSerial.c

@@ -49,24 +49,36 @@ int serialOpen (const char *device, const int baud)
 
   switch (baud)
   {
-    case     50:	myBaud =     B50 ; break ;
-    case     75:	myBaud =     B75 ; break ;
-    case    110:	myBaud =    B110 ; break ;
-    case    134:	myBaud =    B134 ; break ;
-    case    150:	myBaud =    B150 ; break ;
-    case    200:	myBaud =    B200 ; break ;
-    case    300:	myBaud =    B300 ; break ;
-    case    600:	myBaud =    B600 ; break ;
-    case   1200:	myBaud =   B1200 ; break ;
-    case   1800:	myBaud =   B1800 ; break ;
-    case   2400:	myBaud =   B2400 ; break ;
-    case   4800:	myBaud =   B4800 ; break ;
-    case   9600:	myBaud =   B9600 ; break ;
-    case  19200:	myBaud =  B19200 ; break ;
-    case  38400:	myBaud =  B38400 ; break ;
-    case  57600:	myBaud =  B57600 ; break ;
-    case 115200:	myBaud = B115200 ; break ;
-    case 230400:	myBaud = B230400 ; break ;
+    case      50:	myBaud =      B50 ; break ;
+    case      75:	myBaud =      B75 ; break ;
+    case     110:	myBaud =     B110 ; break ;
+    case     134:	myBaud =     B134 ; break ;
+    case     150:	myBaud =     B150 ; break ;
+    case     200:	myBaud =     B200 ; break ;
+    case     300:	myBaud =     B300 ; break ;
+    case     600:	myBaud =     B600 ; break ;
+    case    1200:	myBaud =    B1200 ; break ;
+    case    1800:	myBaud =    B1800 ; break ;
+    case    2400:	myBaud =    B2400 ; break ;
+    case    4800:	myBaud =    B4800 ; break ;
+    case    9600:	myBaud =    B9600 ; break ;
+    case   19200:	myBaud =   B19200 ; break ;
+    case   38400:	myBaud =   B38400 ; break ;
+    case   57600:	myBaud =   B57600 ; break ;
+    case  115200:	myBaud =  B115200 ; break ;
+    case  230400:	myBaud =  B230400 ; break ;
+    case  460800:	myBaud =  B460800 ; break ;
+    case  500000:	myBaud =  B500000 ; break ;
+    case  576000:	myBaud =  B576000 ; break ;
+    case  921600:	myBaud =  B921600 ; break ;
+    case 1000000:	myBaud = B1000000 ; break ;
+    case 1152000:	myBaud = B1152000 ; break ;
+    case 1500000:	myBaud = B1500000 ; break ;
+    case 2000000:	myBaud = B2000000 ; break ;
+    case 2500000:	myBaud = B2500000 ; break ;
+    case 3000000:	myBaud = B3000000 ; break ;
+    case 3500000:	myBaud = B3500000 ; break ;
+    case 4000000:	myBaud = B4000000 ; break ;
 
     default:
       return -2 ;
@@ -96,7 +108,7 @@ int serialOpen (const char *device, const int baud)
     options.c_cc [VMIN]  =   0 ;
     options.c_cc [VTIME] = 100 ;	// Ten seconds (100 deciseconds)
 
-  tcsetattr (fd, TCSANOW | TCSAFLUSH, &options) ;
+  tcsetattr (fd, TCSANOW, &options) ;
 
   ioctl (fd, TIOCMGET, &status);
 

+ 72 - 1
wiringPi/wpiExtensions.c

@@ -55,6 +55,10 @@
 #include "ads1115.h"
 #include "sn3218.h"
 #include "drcSerial.h"
+#include "pseudoPins.h"
+#include "bmp180.h"
+#include "htu21d.h"
+#include "ds18b20.h"
 
 #include "wpiExtensions.h"
 
@@ -428,6 +432,69 @@ static int doExtensionPcf8591 (char *progName, int pinBase, char *params)
 }
 
 
+/*
+ * doExtensionPseudoPins:
+ *	64 Memory resident pseudo pins
+ *	pseudoPins:base
+ *********************************************************************************
+ */
+
+static int doExtensionPseudoPins (UNU char *progName, int pinBase, UNU char *params)
+{
+  pseudoPinsSetup (pinBase) ;
+
+  return TRUE ;
+}
+
+
+/*
+ * doExtensionBmp180:
+ *	Analog Temp + Pressure
+ *	bmp180:base
+ *********************************************************************************
+ */
+
+static int doExtensionBmp180 (UNU char *progName, int pinBase, UNU char *params)
+{
+  bmp180Setup (pinBase) ;
+
+  return TRUE ;
+}
+
+
+/*
+ * doExtensionHtu21d:
+ *	Analog humidity + Pressure
+ *	htu21d:base
+ *********************************************************************************
+ */
+
+static int doExtensionHtu21d (UNU char *progName, int pinBase, UNU char *params)
+{
+  htu21dSetup (pinBase) ;
+
+  return TRUE ;
+}
+
+
+/*
+ * doExtensionDs18b20:
+ *	1-Wire Temperature
+ *	htu21d:base:serialNum
+ *********************************************************************************
+ */
+
+static int doExtensionDs18b20 (char *progName, int pinBase, char *params)
+{
+  char *serialNum ;
+
+  if ((params = extractStr (progName, params, &serialNum)) == NULL)
+    return FALSE ;
+
+  return ds18b20Setup (pinBase, serialNum) ;
+}
+
+
 /*
  * doExtensionMax31855:
  *	Analog IO
@@ -565,7 +632,7 @@ static int doExtensionMcp4802 (char *progName, int pinBase, char *params)
  *********************************************************************************
  */
 
-static int doExtensionSn3218 (char *progName, int pinBase, char *params)
+static int doExtensionSn3218 (UNU char *progName, int pinBase, UNU char *params)
 {
   sn3218Setup (pinBase) ;
   return TRUE ;
@@ -677,6 +744,10 @@ static struct extensionFunctionStruct extensionFunctions [] =
   { "sr595",		&doExtensionSr595	},
   { "pcf8574",		&doExtensionPcf8574	},
   { "pcf8591",		&doExtensionPcf8591	},
+  { "bmp180",		&doExtensionBmp180	},
+  { "pseudoPins",	&doExtensionPseudoPins	},
+  { "htu21d",		&doExtensionHtu21d	},
+  { "ds18b20",		&doExtensionDs18b20	},
   { "mcp3002",		&doExtensionMcp3002	},
   { "mcp3004",		&doExtensionMcp3004	},
   { "mcp4802",		&doExtensionMcp4802	},