From b1dfc186efe327aa1d59de43ef631a2fa24e7c95 Mon Sep 17 00:00:00 2001 From: Gordon Henderson Date: Mon, 12 Dec 2016 14:19:55 +0000 Subject: [PATCH] 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. --- VERSION | 2 +- build | 2 +- debian-template/wiringPi/DEBIAN/control | 2 +- devLib/Makefile | 4 +- devLib/gertboard.c | 2 +- devLib/piFaceOld.c | 3 +- examples/Makefile | 2 +- examples/PiFace/Makefile | 4 +- examples/PiGlow/Makefile | 4 +- examples/q2w/Makefile | 4 +- examples/scrollPhat/Makefile | 4 +- gpio/Makefile | 10 +- gpio/gpio.c | 140 +++++++- gpio/pintest | 2 +- gpio/readall.c | 2 +- gpio/test.sh | 2 +- gpio/version.h | 2 +- newVersion | 2 +- update | 5 + wiringPi/Makefile | 31 +- wiringPi/ads1115.c | 2 +- wiringPi/bmp180.c | 237 ++++++++++++++ wiringPi/bmp180.h | 34 ++ wiringPi/ds18b20.c | 146 +++++++++ wiringPi/ds18b20.h | 34 ++ wiringPi/htu21d.c | 150 +++++++++ wiringPi/htu21d.h | 34 ++ wiringPi/mcp3002.c | 2 +- wiringPi/pseudoPins.c | 95 ++++++ wiringPi/pseudoPins.h | 26 ++ wiringPi/softPwm.c | 16 +- wiringPi/wiringPi.c | 404 ++++++++++++------------ wiringPi/wiringPi.h | 4 +- wiringPi/wiringPiI2C.c | 3 +- wiringPi/wiringPiSPI.c | 9 +- wiringPi/wiringSerial.c | 49 +-- wiringPi/wpiExtensions.c | 72 +++++ 37 files changed, 1255 insertions(+), 291 deletions(-) create mode 100755 update create mode 100644 wiringPi/bmp180.c create mode 100644 wiringPi/bmp180.h create mode 100644 wiringPi/ds18b20.c create mode 100644 wiringPi/ds18b20.h create mode 100644 wiringPi/htu21d.c create mode 100644 wiringPi/htu21d.h create mode 100644 wiringPi/pseudoPins.c create mode 100644 wiringPi/pseudoPins.h diff --git a/VERSION b/VERSION index 0f34dc7..90177b7 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -2.32 +2.36 diff --git a/build b/build index 368e8f4..b42a25a 100755 --- a/build +++ b/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 diff --git a/debian-template/wiringPi/DEBIAN/control b/debian-template/wiringPi/DEBIAN/control index 230da07..d9f2658 100644 --- a/debian-template/wiringPi/DEBIAN/control +++ b/debian-template/wiringPi/DEBIAN/control @@ -1,5 +1,5 @@ Package: wiringpi -Version: 2.32 +Version: 2.36 Section: libraries Priority: optional Architecture: armhf diff --git a/devLib/Makefile b/devLib/Makefile index 1b1ebe0..cf665d6 100644 --- a/devLib/Makefile +++ b/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/ diff --git a/devLib/gertboard.c b/devLib/gertboard.c index 5aeaef7..6a84415 100644 --- a/devLib/gertboard.c +++ b/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 ; } diff --git a/devLib/piFaceOld.c b/devLib/piFaceOld.c index 1b1c0dd..cadbfe8 100644 --- a/devLib/piFaceOld.c +++ b/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. diff --git a/examples/Makefile b/examples/Makefile index 4278b6d..d6195b3 100644 --- a/examples/Makefile +++ b/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 diff --git a/examples/PiFace/Makefile b/examples/PiFace/Makefile index 4685adc..f937c14 100644 --- a/examples/PiFace/Makefile +++ b/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 diff --git a/examples/PiGlow/Makefile b/examples/PiGlow/Makefile index acd4818..f182db7 100644 --- a/examples/PiGlow/Makefile +++ b/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 diff --git a/examples/q2w/Makefile b/examples/q2w/Makefile index 6f50fa0..8f773bf 100644 --- a/examples/q2w/Makefile +++ b/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 diff --git a/examples/scrollPhat/Makefile b/examples/scrollPhat/Makefile index c0b7241..2471f69 100644 --- a/examples/scrollPhat/Makefile +++ b/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 diff --git a/gpio/Makefile b/gpio/Makefile index 7dcd090..cdf954f 100644 --- a/gpio/Makefile +++ b/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: diff --git a/gpio/gpio.c b/gpio/gpio.c index 6162090..c954f3b 100644 --- a/gpio/gpio.c +++ b/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] ...\n" " gpio ...\n" + " gpio \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 \n" " gpio usbp high/low\n" " gpio gbr \n" " gpio gbw " ; // 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 diff --git a/gpio/pintest b/gpio/pintest index 4da3d94..b574361 100755 --- a/gpio/pintest +++ b/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 diff --git a/gpio/readall.c b/gpio/readall.c index cb7e18f..c447e5e 100644 --- a/gpio/readall.c +++ b/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 ", diff --git a/gpio/test.sh b/gpio/test.sh index a7c2bb2..708f1d3 100755 --- a/gpio/test.sh +++ b/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 diff --git a/gpio/version.h b/gpio/version.h index 5b92dc9..687cc74 100644 --- a/gpio/version.h +++ b/gpio/version.h @@ -1 +1 @@ -#define VERSION "2.32" +#define VERSION "2.36" diff --git a/newVersion b/newVersion index bab6dc5..299d7a7 100755 --- a/newVersion +++ b/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 diff --git a/update b/update new file mode 100755 index 0000000..0f72243 --- /dev/null +++ b/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/ . diff --git a/wiringPi/Makefile b/wiringPi/Makefile index acb6e58..ffe0012 100644 --- a/wiringPi/Makefile +++ b/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 diff --git a/wiringPi/ads1115.c b/wiringPi/ads1115.c index 62b92f8..648e612 100644 --- a/wiringPi/ads1115.c +++ b/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)" - Thanks. } } diff --git a/wiringPi/bmp180.c b/wiringPi/bmp180.c new file mode 100644 index 0000000..bad4bb3 --- /dev/null +++ b/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 . + *********************************************************************** + */ + +#include +#include +#include +#include + +#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 ; +} diff --git a/wiringPi/bmp180.h b/wiringPi/bmp180.h new file mode 100644 index 0000000..4a6d13a --- /dev/null +++ b/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 . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int bmp180Setup (const int pinBase) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/ds18b20.c b/wiringPi/ds18b20.c new file mode 100644 index 0000000..533398e --- /dev/null +++ b/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 . + *********************************************************************** + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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 ; +} diff --git a/wiringPi/ds18b20.h b/wiringPi/ds18b20.h new file mode 100644 index 0000000..a9ea291 --- /dev/null +++ b/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 . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int ds18b20Setup (const int pinBase, const char *serialNum) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/htu21d.c b/wiringPi/htu21d.c new file mode 100644 index 0000000..9028d60 --- /dev/null +++ b/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 . + *********************************************************************** + */ + +#include +#include +#include +#include + +#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 ; +} diff --git a/wiringPi/htu21d.h b/wiringPi/htu21d.h new file mode 100644 index 0000000..3965c54 --- /dev/null +++ b/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 . + *********************************************************************** + */ + +#ifdef __cplusplus +extern "C" { +#endif + +extern int htu21dSetup (const int pinBase) ; + +#ifdef __cplusplus +} +#endif diff --git a/wiringPi/mcp3002.c b/wiringPi/mcp3002.c index 8e191b6..9ebf3e4 100644 --- a/wiringPi/mcp3002.c +++ b/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 ; } diff --git a/wiringPi/pseudoPins.c b/wiringPi/pseudoPins.c new file mode 100644 index 0000000..c2bf5e0 --- /dev/null +++ b/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 . + *********************************************************************** + */ + +#define SHARED_NAME "wiringPiPseudoPins" +#define PSEUDO_PINS 64 + +#include +#include +#include +#include +#include + +#include + +#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 ; +} diff --git a/wiringPi/pseudoPins.h b/wiringPi/pseudoPins.h new file mode 100644 index 0000000..bef4660 --- /dev/null +++ b/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 . + *********************************************************************** + */ + +extern int pseudoPinsSetup (const int pinBase) ; diff --git a/wiringPi/softPwm.c b/wiringPi/softPwm.c index 98b408f..5999cc0 100644 --- a/wiringPi/softPwm.c +++ b/wiringPi/softPwm.c @@ -23,6 +23,7 @@ */ #include +#include #include #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, ¶m) ; + 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) ; diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index dfd5de4..5adfe69 100644 --- a/wiringPi/wiringPi.c +++ b/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)") ; + piGpioLayoutOops ("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") ; -*******************/ - -// 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. - /**/ if (boardRev == 1) // A, B, Rev 1, 1.1 + piBoardId (&model, &rev, &mem, &maker, &overVolted) ; + + if (model == PI_MODEL_CM) + 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 +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 ; diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index e11a0be..7926296 100644 --- a/wiringPi/wiringPi.h +++ b/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) ; diff --git a/wiringPi/wiringPiI2C.c b/wiringPi/wiringPiI2C.c index c787bce..b0ee5d3 100644 --- a/wiringPi/wiringPiI2C.c +++ b/wiringPi/wiringPiI2C.c @@ -52,6 +52,7 @@ #include #include #include +#include #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" ; diff --git a/wiringPi/wiringPiSPI.c b/wiringPi/wiringPiSPI.c index 453df31..022b99f 100644 --- a/wiringPi/wiringPiSPI.c +++ b/wiringPi/wiringPiSPI.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #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] ; diff --git a/wiringPi/wiringSerial.c b/wiringPi/wiringSerial.c index ca976a9..09aeb35 100644 --- a/wiringPi/wiringSerial.c +++ b/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); diff --git a/wiringPi/wpiExtensions.c b/wiringPi/wpiExtensions.c index 62a92d7..96852b7 100644 --- a/wiringPi/wpiExtensions.c +++ b/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 },