Browse Source

A new version of wiringPi. Added in more stuff and fixed it up
for kernels 4.8 onwards.

Some very old stuff might break.

Additional fixes for the ISR code and some tweaks here and
there. I've removed the checks for some operations that might
fail when using the gpiomem interface - which is now the default
way of doing things - if your program segfaults, then you
may need to use sudo on it.

Gordon Henderson 7 years ago
parent
commit
b1dfc186ef

+ 1 - 1
VERSION

@@ -1 +1 @@
-2.32
+2.36

+ 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

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

@@ -1,5 +1,5 @@
 Package: wiringpi
-Version: 2.32
+Version: 2.36
 Section: libraries
 Priority: optional
 Architecture: armhf

+ 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

+ 6 - 4
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:

+ 125 - 15
gpio/gpio.c

@@ -57,6 +57,8 @@ 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 ;
 
@@ -65,6 +67,7 @@ char *usage = "Usage: gpio -v\n"
               "       gpio [-g|-1] [-x extension:params] ...\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 +79,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 +107,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 +274,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 +339,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) ;
   }
 }
@@ -312,11 +359,10 @@ static void doUnLoad (int argc, char *argv [])
 
 static void doI2Cdetect (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 +374,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)) ;
 
@@ -943,7 +990,7 @@ static void doAwrite (int argc, char *argv [])
 
 /*
  * doWriteByte:
- *	gpio write value
+ *	gpio wb value
  *********************************************************************************
  */
 
@@ -963,6 +1010,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 +1097,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,6 +1261,8 @@ 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") ;
@@ -1179,12 +1280,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 +1332,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 ;
   }
 
@@ -1375,6 +1482,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 +1499,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/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

+ 1 - 1
gpio/readall.c

@@ -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    ",

+ 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

+ 1 - 1
gpio/version.h

@@ -1 +1 @@
-#define VERSION "2.32"
+#define VERSION "2.36"

+ 1 - 1
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

+ 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/ .

+ 12 - 19
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] $<
@@ -174,9 +163,13 @@ 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
 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 bmp180.h htu21d.h ds18b20.h 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 (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 ;
 }
 
 

+ 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) ;

+ 204 - 200
wiringPi/wiringPi.c

@@ -129,9 +129,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 +196,23 @@ static volatile uint32_t *timer ;
 static volatile uint32_t *timerIrqRaw ;
 #endif
 
+// GCC warning suppressor
+
+#define	UNU	__attribute__((unused))
+
 
 // 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] =
 {
@@ -649,7 +658,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 +675,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 +713,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 +737,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 +753,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 +761,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 +770,7 @@ int piBoardRev (void)
       break ;
 
   if (*c != ':')
-    piBoardRevOops ("Bogus \"Revision\" line (no colon)") ;
+    piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ;
 
 // Chomp spaces
 
@@ -763,46 +779,46 @@ 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 ;
 }
 
+/***
+  if (strstr (line, "BCM2709") != NULL)	// Pi v2 - no point doing anything more at this point
+  {
+    piModel2 = TRUE ;
+    fclose (cpuFd) ;
+    return gpioLayout = 2 ;
+  }
+  else if (strstr (line, "BCM2708") == NULL)
+  {
+  }
+***/
+
+// 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.
+
 
 /*
  * piBoardId:
@@ -822,20 +838,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 +898,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 +910,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 +929,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 +938,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
 
@@ -944,12 +972,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 +991,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 +1063,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 +1136,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 +1157,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 +1209,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 +1251,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 +1381,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 +1400,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 +1554,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 +1620,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 +1644,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 +1734,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 +1786,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 +1813,7 @@ int waitForInterrupt (int pin, int mS)
  *********************************************************************************
  */
 
-static void *interruptHandler (void *arg)
+static void *interruptHandler (UNU void *arg)
 {
   int myPin ;
 
@@ -2047,18 +2063,17 @@ unsigned int micros (void)
 int wiringPiSetup (void)
 {
   int   fd ;
-  int   boardRev ;
   int   model, rev, mem, maker, overVolted ;
-  static int alreadyCalled = FALSE ;
+  static int alreadyDoneThis = 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.
+// 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.
 
-  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") ;
-
-  alreadyCalled = TRUE ;
+  if (alreadyDoneThis)
+    return 0 ;
 
+  alreadyDoneThis = TRUE ;
 
   if (getenv (ENV_DEBUG) != NULL)
     wiringPiDebug = TRUE ;
@@ -2066,101 +2081,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.
+
+  piBoardId (&model, &rev, &mem, &maker, &overVolted) ;
+
+  if (model == PI_MODEL_CM)
+    wiringPiMode = WPI_MODE_GPIO ;
+  else
+    wiringPiMode = WPI_MODE_PINS ;
 
-  /**/ if (boardRev == 1)	// A, B, Rev 1, 1.1
+  /**/ 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 +2187,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 +2246,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 +2269,7 @@ int wiringPiSetupSys (void)
   if (wiringPiDebug)
     printf ("wiringPi: wiringPiSetupSys called\n") ;
 
-  boardRev = piBoardRev () ;
-
-  if (boardRev == 1)
+  if (piGpioLayout () == 1)
   {
      pinToGpio =  pinToGpioR1 ;
     physToGpio = physToGpioR1 ;

+ 2 - 2
wiringPi/wiringPi.h

@@ -95,7 +95,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] ;
@@ -190,7 +190,7 @@ 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          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] ;

+ 30 - 19
wiringPi/wiringSerial.c

@@ -49,24 +49,35 @@ 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    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 +107,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 - 0
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,70 @@ static int doExtensionPcf8591 (char *progName, int pinBase, char *params)
 }
 
 
+/*
+ * doExtensionPseudoPins:
+ *	64 Memory resident pseudo pins
+ *	pseudoPins:base
+ *********************************************************************************
+ */
+
+static int doExtensionPseudoPins (char *progName, int pinBase, char *params)
+{
+  pseudoPinsSetup (pinBase) ;
+printf ("pseudoPins: %d\n", pinBase) ;
+
+  return TRUE ;
+}
+
+
+/*
+ * doExtensionBmp180:
+ *	Analog Temp + Pressure
+ *	bmp180:base
+ *********************************************************************************
+ */
+
+static int doExtensionBmp180 (char *progName, int pinBase, char *params)
+{
+  bmp180Setup (pinBase) ;
+
+  return TRUE ;
+}
+
+
+/*
+ * doExtensionHtu21d:
+ *	Analog humidity + Pressure
+ *	htu21d:base
+ *********************************************************************************
+ */
+
+static int doExtensionHtu21d (char *progName, int pinBase, 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
@@ -677,6 +745,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	},