@@ -1 +1 @@ | |||
2.32 | |||
2.39 |
@@ -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,5 +1,5 @@ | |||
Package: wiringpi | |||
Version: 2.32 | |||
Version: 2.38 | |||
Section: libraries | |||
Priority: optional | |||
Architecture: armhf | |||
@@ -7,4 +7,4 @@ Depends: libc6 | |||
Maintainer: Gordon Henderson <projects@drogon.net> | |||
Description: The wiringPi libraries, headers and gpio command | |||
Libraries to allow GPIO access on a Raspberry Pi from C and C++ | |||
programs as well as from the command-line | |||
and BASIC programs as well as from the command-line |
@@ -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/ | |||
@@ -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,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,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 | |||
@@ -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 | |||
@@ -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 | |||
@@ -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 | |||
@@ -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 | |||
@@ -4,10 +4,10 @@ | |||
# A swiss-army knige of GPIO shenanigans. | |||
# https://projects.drogon.net/wiring-pi | |||
# | |||
# Copyright (c) 2012-2015 Gordon Henderson | |||
# Copyright (c) 2012-2016 Gordon Henderson | |||
################################################################################# | |||
# This file is part of wiringPi: | |||
# Wiring Compatable library for the Raspberry Pi | |||
# A "wiring" library for the Raspberry Pi | |||
# | |||
# wiringPi is free software: you can redistribute it and/or modify | |||
# it under the terms of the GNU Lesser General Public License as published by | |||
@@ -34,10 +34,10 @@ endif | |||
DEBUG = -O2 | |||
CC = gcc | |||
INCLUDE = -I$(DESTDIR)$(PREFIX)/include | |||
CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe | |||
CFLAGS = $(DEBUG) -Wall -Wextra $(INCLUDE) -Winline -pipe | |||
LDFLAGS = -L$(DESTDIR)$(PREFIX)/lib | |||
LIBS = -lwiringPi -lwiringPiDev -lpthread | |||
LIBS = -lwiringPi -lwiringPiDev -lpthread -lrt -lm | |||
# May not need to alter anything below this line | |||
############################################################################### | |||
@@ -85,6 +85,8 @@ install-deb: gpio | |||
$Q echo "[Install: deb]" | |||
$Q install -m 0755 -d ~/wiringPi/debian-template/wiringPi/usr/bin | |||
$Q install -m 0755 gpio ~/wiringPi/debian-template/wiringPi/usr/bin | |||
$Q install -m 0755 -d ~/wiringPi/debian-template/wiringPi/man/man1 | |||
$Q install -m 0644 gpio.1 ~/wiringPi/debian-template/wiringPi/man/man1 | |||
.PHONY: uninstall | |||
uninstall: | |||
@@ -98,4 +100,4 @@ depend: | |||
# DO NOT DELETE | |||
gpio.o: version.h | |||
gpio.o: ../version.h |
@@ -2,7 +2,7 @@ | |||
* gpio.c: | |||
* Swiss-Army-Knife, Set-UID command-line interface to the Raspberry | |||
* Pi's GPIO. | |||
* Copyright (c) 2012-2015 Gordon Henderson | |||
* Copyright (c) 2012-2017 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
@@ -40,7 +40,7 @@ | |||
#include <gertboard.h> | |||
#include <piFace.h> | |||
#include "version.h" | |||
#include "../version.h" | |||
extern int wiringPiDebug ; | |||
@@ -57,14 +57,19 @@ extern void doPins (void) ; | |||
#define PI_USB_POWER_CONTROL 38 | |||
#define I2CDETECT "/usr/sbin/i2cdetect" | |||
#define MODPROBE "/sbin/modprobe" | |||
#define RMMOD "/sbin/rmmod" | |||
int wpMode ; | |||
char *usage = "Usage: gpio -v\n" | |||
" gpio -h\n" | |||
" gpio [-g|-1] [-x extension:params] ...\n" | |||
" gpio [-g|-1] ...\n" | |||
" gpio [-d] ...\n" | |||
" [-x extension:params] [[ -x ...]] ...\n" | |||
" gpio [-p] <read/write/wb> ...\n" | |||
" gpio <read/write/aread/awritewb/pwm/clock/mode> ...\n" | |||
" gpio <toggle/blink> <pin>\n" | |||
" gpio readall/reset\n" | |||
" gpio unexportall/exports\n" | |||
" gpio export/edge/unexport ...\n" | |||
@@ -76,6 +81,8 @@ char *usage = "Usage: gpio -v\n" | |||
" gpio load spi/i2c\n" | |||
" gpio unload spi/i2c\n" | |||
" gpio i2cd/i2cdetect\n" | |||
" gpio rbx/rbd\n" | |||
" gpio wb <value>\n" | |||
" gpio usbp high/low\n" | |||
" gpio gbr <channel>\n" | |||
" gpio gbw <channel> <value>" ; // No trailing newline needed here. | |||
@@ -103,6 +110,45 @@ static int decodePin (const char *str) | |||
/* | |||
* 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 | |||
* program so we can access it. | |||
@@ -230,15 +276,18 @@ static void doLoad (int argc, char *argv []) | |||
else | |||
_doLoadUsage (argv) ; | |||
if (findExecutable ("modprobe") == NULL) | |||
printf ("No found\n") ; | |||
if (!moduleLoaded (module1)) | |||
{ | |||
sprintf (cmd, "/sbin/modprobe %s%s", module1, args1) ; | |||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module1, args1) ; | |||
system (cmd) ; | |||
} | |||
if (!moduleLoaded (module2)) | |||
{ | |||
sprintf (cmd, "/sbin/modprobe %s%s", module2, args2) ; | |||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module2, args2) ; | |||
system (cmd) ; | |||
} | |||
@@ -292,13 +341,13 @@ static void doUnLoad (int argc, char *argv []) | |||
if (moduleLoaded (module1)) | |||
{ | |||
sprintf (cmd, "/sbin/rmmod %s", module1) ; | |||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module1) ; | |||
system (cmd) ; | |||
} | |||
if (moduleLoaded (module2)) | |||
{ | |||
sprintf (cmd, "/sbin/rmmod %s", module2) ; | |||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module2) ; | |||
system (cmd) ; | |||
} | |||
} | |||
@@ -310,13 +359,12 @@ static void doUnLoad (int argc, char *argv []) | |||
********************************************************************************* | |||
*/ | |||
static void doI2Cdetect (int argc, char *argv []) | |||
static void doI2Cdetect (UNU int argc, char *argv []) | |||
{ | |||
int port = piBoardRev () == 1 ? 0 : 1 ; | |||
char command [128] ; | |||
struct stat statBuf ; | |||
int port = piGpioLayout () == 1 ? 0 : 1 ; | |||
char *c, *command ; | |||
if (stat (I2CDETECT, &statBuf) < 0) | |||
if ((c = findExecutable (I2CDETECT)) == NULL) | |||
{ | |||
fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ; | |||
return ; | |||
@@ -328,7 +376,8 @@ static void doI2Cdetect (int argc, char *argv []) | |||
return ; | |||
} | |||
sprintf (command, "%s -y %d", I2CDETECT, port) ; | |||
command = malloc (strlen (c) + 16) ; | |||
sprintf (command, "%s -y %d", c, port) ; | |||
if (system (command) < 0) | |||
fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ; | |||
@@ -341,7 +390,7 @@ static void doI2Cdetect (int argc, char *argv []) | |||
********************************************************************************* | |||
*/ | |||
static void doExports (int argc, char *argv []) | |||
static void doExports (UNU int argc, UNU char *argv []) | |||
{ | |||
int fd ; | |||
int i, l, first ; | |||
@@ -667,7 +716,7 @@ void doUnexportall (char *progName) | |||
********************************************************************************* | |||
*/ | |||
static void doReset (char *progName) | |||
static void doReset (UNU char *progName) | |||
{ | |||
printf ("GPIO Reset is dangerous and has been removed from the gpio command.\n") ; | |||
printf (" - Please write a shell-script to reset the GPIO pins into the state\n") ; | |||
@@ -943,7 +992,7 @@ static void doAwrite (int argc, char *argv []) | |||
/* | |||
* doWriteByte: | |||
* gpio write value | |||
* gpio wb value | |||
********************************************************************************* | |||
*/ | |||
@@ -964,6 +1013,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 | |||
********************************************************************************* | |||
@@ -1027,6 +1100,34 @@ void doToggle (int argc, char *argv []) | |||
/* | |||
* doBlink: | |||
* Blink an IO pin | |||
********************************************************************************* | |||
*/ | |||
void doBlink (int argc, char *argv []) | |||
{ | |||
int pin ; | |||
if (argc != 3) | |||
{ | |||
fprintf (stderr, "Usage: %s blink pin\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
pin = atoi (argv [2]) ; | |||
pinMode (pin, OUTPUT) ; | |||
for (;;) | |||
{ | |||
digitalWrite (pin, !digitalRead (pin)) ; | |||
delay (500) ; | |||
} | |||
} | |||
/* | |||
* doPwmTone: | |||
* Output a tone in a PWM pin | |||
********************************************************************************* | |||
@@ -1162,9 +1263,14 @@ static void doVersion (char *argv []) | |||
{ | |||
int model, rev, mem, maker, warranty ; | |||
struct stat statBuf ; | |||
char name [80] ; | |||
FILE *fd ; | |||
printf ("gpio version: %s\n", VERSION) ; | |||
printf ("Copyright (c) 2012-2015 Gordon Henderson\n") ; | |||
int vMaj, vMin ; | |||
wiringPiVersion (&vMaj, &vMin) ; | |||
printf ("gpio version: %d.%d\n", vMaj, vMin) ; | |||
printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ; | |||
printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ; | |||
printf ("For details type: %s -warranty\n", argv [0]) ; | |||
printf ("\n") ; | |||
@@ -1179,12 +1285,18 @@ static void doVersion (char *argv []) | |||
if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ... | |||
printf (" * Device tree is enabled.\n") ; | |||
if (stat ("/dev/gpiomem", &statBuf) == 0) // User level GPIO is GO | |||
if (stat ("/proc/device-tree/model", &statBuf) == 0) // Output Kernel idea of board type | |||
{ | |||
printf (" * This Raspberry Pi supports user-level GPIO access.\n") ; | |||
printf (" -> See the man-page for more details\n") ; | |||
printf (" -> ie. export WIRINGPI_GPIOMEM=1\n") ; | |||
if ((fd = fopen ("/proc/device-tree/model", "r")) != NULL) | |||
{ | |||
fgets (name, 80, fd) ; | |||
fclose (fd) ; | |||
printf (" *--> %s\n", name) ; | |||
} | |||
} | |||
if (stat ("/dev/gpiomem", &statBuf) == 0) // User level GPIO is GO | |||
printf (" * This Raspberry Pi supports user-level GPIO access.\n") ; | |||
else | |||
printf (" * Root or sudo required for GPIO access.\n") ; | |||
} | |||
@@ -1225,7 +1337,7 @@ int main (int argc, char *argv []) | |||
if ((strcmp (argv [1], "-R") == 0) || (strcmp (argv [1], "-V") == 0)) | |||
{ | |||
printf ("%d\n", piBoardRev ()) ; | |||
printf ("%d\n", piGpioLayout ()) ; | |||
return 0 ; | |||
} | |||
@@ -1240,7 +1352,7 @@ int main (int argc, char *argv []) | |||
if (strcasecmp (argv [1], "-warranty") == 0) | |||
{ | |||
printf ("gpio version: %s\n", VERSION) ; | |||
printf ("Copyright (c) 2012-2015 Gordon Henderson\n") ; | |||
printf ("Copyright (c) 2012-2017 Gordon Henderson\n") ; | |||
printf ("\n") ; | |||
printf (" This program is free software; you can redistribute it and/or modify\n") ; | |||
printf (" it under the terms of the GNU Leser General Public License as published\n") ; | |||
@@ -1340,8 +1452,11 @@ int main (int argc, char *argv []) | |||
} | |||
// Check for -x argument to load in a new extension | |||
// -x extension:base:args | |||
// Can load many modules, but unless daemon mode we can only send one | |||
// command at a time. | |||
if (strcasecmp (argv [1], "-x") == 0) | |||
while (strcasecmp (argv [1], "-x") == 0) | |||
{ | |||
if (argc < 3) | |||
{ | |||
@@ -1352,6 +1467,8 @@ int main (int argc, char *argv []) | |||
if (!loadWPiExtension (argv [0], argv [2], TRUE)) // Prints its own error messages | |||
exit (EXIT_FAILURE) ; | |||
// Shift args down by 2 | |||
for (i = 3 ; i < argc ; ++i) | |||
argv [i - 2] = argv [i] ; | |||
argc -= 2 ; | |||
@@ -1375,6 +1492,7 @@ int main (int argc, char *argv []) | |||
// GPIO Nicies | |||
else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle (argc, argv) ; | |||
else if (strcasecmp (argv [1], "blink" ) == 0) doBlink (argc, argv) ; | |||
// Pi Specifics | |||
@@ -1391,6 +1509,8 @@ int main (int argc, char *argv []) | |||
else if (strcasecmp (argv [1], "i2cd" ) == 0) doI2Cdetect (argc, argv) ; | |||
else if (strcasecmp (argv [1], "reset" ) == 0) doReset (argv [0]) ; | |||
else if (strcasecmp (argv [1], "wb" ) == 0) doWriteByte (argc, argv) ; | |||
else if (strcasecmp (argv [1], "rbx" ) == 0) doReadByte (argc, argv, TRUE) ; | |||
else if (strcasecmp (argv [1], "rbd" ) == 0) doReadByte (argc, argv, FALSE) ; | |||
else if (strcasecmp (argv [1], "clock" ) == 0) doClock (argc, argv) ; | |||
else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ; | |||
else | |||
@@ -1,7 +1,7 @@ | |||
/* | |||
* pins.c: | |||
* Just display a handy Pi pinnout diagram. | |||
* Copyright (c) 2012-2015 Gordon Henderson | |||
* Copyright (c) 2012-2017 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
@@ -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,7 +1,7 @@ | |||
/* | |||
* readall.c: | |||
* The readall functions - getting a bit big, so split them out. | |||
* Copyright (c) 2012-2015 Gordon Henderson | |||
* Copyright (c) 2012-2017 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
@@ -118,7 +118,7 @@ static char *physNames [64] = | |||
NULL, | |||
" 3.3v", "5v ", | |||
" SDA.1", "5V ", | |||
" SDA.1", "5v ", | |||
" SCL.1", "0v ", | |||
"GPIO. 7", "TxD ", | |||
" 0v", "RxD ", | |||
@@ -348,7 +348,7 @@ void doReadall (void) | |||
abReadall (model, rev) ; | |||
else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || (model == PI_MODEL_2) || (model == PI_MODEL_3) || (model == PI_MODEL_ZERO)) | |||
piPlusReadall (model) ; | |||
else if (model == PI_MODEL_CM) | |||
else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3)) | |||
allReadall () ; | |||
else | |||
printf ("Oops - unable to determine board type... model: %d\n", model) ; | |||
@@ -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 +0,0 @@ | |||
#define VERSION "2.32" |
@@ -7,7 +7,7 @@ | |||
# Copyright (c) 2012-2015 Gordon Henderson | |||
################################################################################# | |||
# This file is part of wiringPi: | |||
# Wiring Compatable library for the Raspberry Pi | |||
# A "wiring" library for the Raspberry Pi | |||
# | |||
# wiringPi is free software: you can redistribute it and/or modify | |||
# it under the terms of the GNU Lesser General Public License as published by | |||
@@ -25,8 +25,12 @@ | |||
echo Updating to version: `cat VERSION` | |||
rm -f gpio/version.h | |||
echo "#define VERSION \"`cat VERSION`\"" > gpio/version.h | |||
rm -f version.h | |||
vMaj=`cut -d. -f1 VERSION` | |||
vMin=`cut -d. -f2 VERSION` | |||
echo "#define VERSION \"`cat VERSION`\"" > version.h | |||
echo "#define VERSION_MAJOR $vMaj" >> version.h | |||
echo "#define VERSION_MINOR $vMin" >> version.h | |||
rm -f debian-template/wiringPi/DEBIAN/control | |||
cat > debian-template/wiringPi/DEBIAN/control <<EOF | |||
@@ -39,5 +43,5 @@ Depends: libc6 | |||
Maintainer: Gordon Henderson <projects@drogon.net> | |||
Description: The wiringPi libraries, headers and gpio command | |||
Libraries to allow GPIO access on a Raspberry Pi from C and C++ | |||
programs as well as from the command-line | |||
and BASIC programs as well as from the command-line | |||
EOF |
@@ -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/ . |
@@ -0,0 +1,3 @@ | |||
#define VERSION "2.38" | |||
#define VERSION_MAJOR 2 | |||
#define VERSION_MINOR 38 |
@@ -39,9 +39,9 @@ DEBUG = -O2 | |||
CC = gcc | |||
INCLUDE = -I. | |||
DEFS = -D_GNU_SOURCE | |||
CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Winline $(INCLUDE) -pipe -fPIC | |||
CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Wextra -Winline $(INCLUDE) -pipe -fPIC | |||
LIBS = | |||
LIBS = -lm -lpthread -lrt | |||
############################################################################### | |||
@@ -57,23 +57,12 @@ SRC = wiringPi.c \ | |||
mcp3002.c mcp3004.c mcp4802.c mcp3422.c \ | |||
max31855.c max5322.c ads1115.c \ | |||
sn3218.c \ | |||
bmp180.c htu21d.c ds18b20.c \ | |||
drcSerial.c \ | |||
pseudoPins.c \ | |||
wpiExtensions.c | |||
HEADERS = wiringPi.h \ | |||
wiringSerial.h wiringShift.h \ | |||
wiringPiSPI.h wiringPiI2C.h \ | |||
softPwm.h softTone.h \ | |||
mcp23008.h mcp23016.h mcp23017.h \ | |||
mcp23s08.h mcp23s17.h \ | |||
sr595.h \ | |||
pcf8574.h pcf8591.h \ | |||
mcp3002.h mcp3004.h mcp4802.h mcp3422.h \ | |||
max31855.h max5322.h ads1115.h \ | |||
sn3218.h \ | |||
drcSerial.h \ | |||
wpiExtensions.h | |||
HEADERS = $(shell ls *.h) | |||
OBJ = $(SRC:.c=.o) | |||
@@ -89,7 +78,7 @@ $(STATIC): $(OBJ) | |||
$(DYNAMIC): $(OBJ) | |||
$Q echo "[Link (Dynamic)]" | |||
$Q $(CC) -shared -Wl,-soname,libwiringPi.so$(WIRINGPI_SONAME_SUFFIX) -o libwiringPi.so.$(VERSION) -lpthread $(OBJ) | |||
$Q $(CC) -shared -Wl,-soname,libwiringPi.so$(WIRINGPI_SONAME_SUFFIX) -o libwiringPi.so.$(VERSION) $(LIBS) $(OBJ) | |||
.c.o: | |||
$Q echo [Compile] $< | |||
@@ -151,7 +140,7 @@ depend: | |||
# DO NOT DELETE | |||
wiringPi.o: softPwm.h softTone.h wiringPi.h | |||
wiringPi.o: softPwm.h softTone.h wiringPi.h ../version.h | |||
wiringSerial.o: wiringSerial.h | |||
wiringShift.o: wiringPi.h wiringShift.h | |||
piHiPri.o: wiringPi.h | |||
@@ -174,9 +163,15 @@ mcp4802.o: wiringPi.h wiringPiSPI.h mcp4802.h | |||
mcp3422.o: wiringPi.h wiringPiI2C.h mcp3422.h | |||
max31855.o: wiringPi.h wiringPiSPI.h max31855.h | |||
max5322.o: wiringPi.h wiringPiSPI.h max5322.h | |||
ads1115.o: wiringPi.h wiringPiI2C.h ads1115.h | |||
sn3218.o: wiringPi.h wiringPiI2C.h sn3218.h | |||
bmp180.o: wiringPi.h wiringPiI2C.h bmp180.h | |||
htu21d.o: wiringPi.h wiringPiI2C.h htu21d.h | |||
ds18b20.o: wiringPi.h ds18b20.h | |||
drcSerial.o: wiringPi.h wiringSerial.h drcSerial.h | |||
pseudoPins.o: wiringPi.h pseudoPins.h | |||
wpiExtensions.o: wiringPi.h mcp23008.h mcp23016.h mcp23017.h mcp23s08.h | |||
wpiExtensions.o: mcp23s17.h sr595.h pcf8574.h pcf8591.h mcp3002.h mcp3004.h | |||
wpiExtensions.o: mcp4802.h mcp3422.h max31855.h max5322.h sn3218.h | |||
wpiExtensions.o: drcSerial.h wpiExtensions.h | |||
wpiExtensions.o: mcp4802.h mcp3422.h max31855.h max5322.h ads1115.h sn3218.h | |||
wpiExtensions.o: drcSerial.h pseudoPins.h bmp180.h htu21d.h ds18b20.h | |||
wpiExtensions.o: wpiExtensions.h |
@@ -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. | |||
} | |||
} | |||
@@ -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 ; | |||
} |
@@ -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 |
@@ -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 ; | |||
} |
@@ -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 |
@@ -0,0 +1,150 @@ | |||
/* | |||
* htu21d.c: | |||
* Extend wiringPi with the HTU21D I2C humidity and Temperature | |||
* sensor. This is used in the Pi Weather station. | |||
* Copyright (c) 2016 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
* | |||
* wiringPi is free software: you can redistribute it and/or modify | |||
* it under the terms of the GNU Lesser General Public License as | |||
* published by the Free Software Foundation, either version 3 of the | |||
* License, or (at your option) any later version. | |||
* | |||
* wiringPi is distributed in the hope that it will be useful, | |||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
* GNU Lesser General Public License for more details. | |||
* | |||
* You should have received a copy of the GNU Lesser General Public | |||
* License along with wiringPi. | |||
* If not, see <http://www.gnu.org/licenses/>. | |||
*********************************************************************** | |||
*/ | |||
#include <unistd.h> | |||
#include <stdint.h> | |||
#include <stdio.h> | |||
#include <math.h> | |||
#include "wiringPi.h" | |||
#include "wiringPiI2C.h" | |||
#include "htu21d.h" | |||
#define DEBUG | |||
#undef FAKE_SENSOR | |||
#define I2C_ADDRESS 0x40 | |||
int checksum (UNU uint8_t data [4]) | |||
{ | |||
return TRUE ; | |||
} | |||
/* | |||
* myAnalogRead: | |||
********************************************************************************* | |||
*/ | |||
static int myAnalogRead (struct wiringPiNodeStruct *node, int pin) | |||
{ | |||
int chan = pin - node->pinBase ; | |||
int fd = node->fd ; | |||
uint8_t data [4] ; | |||
uint32_t sTemp, sHumid ; | |||
double fTemp, fHumid ; | |||
int cTemp, cHumid ; | |||
/**/ if (chan == 0) // Read Temperature | |||
{ | |||
// Send read temperature command: | |||
data [0] = 0xF3 ; | |||
if (write (fd, data, 1) != 1) | |||
return -9999 ; | |||
// Wait then read the data | |||
delay (50) ; | |||
if (read (fd, data, 3) != 3) | |||
return -9998 ; | |||
if (!checksum (data)) | |||
return -9997 ; | |||
// Do the calculation | |||
sTemp = (data [0] << 8) | data [1] ; | |||
fTemp = -48.85 + 175.72 * (double)sTemp / 63356.0 ; | |||
cTemp = (int)rint (((100.0 * fTemp) + 0.5) / 10.0) ; | |||
return cTemp ; | |||
} | |||
else if (chan == 1) // humidity | |||
{ | |||
// Send read humidity command: | |||
data [0] = 0xF5 ; | |||
if (write (fd, data, 1) != 1) | |||
return -9999 ; | |||
// Wait then read the data | |||
delay (50) ; | |||
if (read (fd, data, 3) != 3) | |||
return -9998 ; | |||
if (!checksum (data)) | |||
return -9997 ; | |||
sHumid = (data [0] << 8) | data [1] ; | |||
fHumid = -6.0 + 125.0 * (double)sHumid / 65536.0 ; | |||
cHumid = (int)rint (((100.0 * fHumid) + 0.5) / 10.0) ; | |||
return cHumid ; | |||
} | |||
else | |||
return -9999 ; | |||
} | |||
/* | |||
* htu21dSetup: | |||
* Create a new instance of a HTU21D I2C GPIO interface. | |||
* This chip has a fixed I2C address, so we are not providing any | |||
* allowance to change this. | |||
********************************************************************************* | |||
*/ | |||
int htu21dSetup (const int pinBase) | |||
{ | |||
int fd ; | |||
struct wiringPiNodeStruct *node ; | |||
uint8_t data ; | |||
int status ; | |||
if ((fd = wiringPiI2CSetup (I2C_ADDRESS)) < 0) | |||
return FALSE ; | |||
node = wiringPiNewNode (pinBase, 2) ; | |||
node->fd = fd ; | |||
node->analogRead = myAnalogRead ; | |||
// Send a reset code to it: | |||
data = 0xFE ; | |||
if (write (fd, &data, 1) != 1) | |||
return FALSE ; | |||
delay (15) ; | |||
// Read the status register to check it's really there | |||
status = wiringPiI2CReadReg8 (fd, 0xE7) ; | |||
return (status == 0x02) ? TRUE : FALSE ; | |||
} |
@@ -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 |
@@ -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 ; | |||
} | |||
@@ -36,7 +36,7 @@ | |||
********************************************************************************* | |||
*/ | |||
static void myAnalogWrite (struct wiringPiNodeStruct *node, int pin, int value) | |||
static void myAnalogWrite (struct wiringPiNodeStruct *node, UNU int pin, int value) | |||
{ | |||
unsigned char b [2] ; | |||
b [0] = 0x40 ; | |||
@@ -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 ; | |||
} |
@@ -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) ; |
@@ -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, ¶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) ; | |||
@@ -1,7 +1,7 @@ | |||
/* | |||
* wiringPi: | |||
* Arduino look-a-like Wiring library for the Raspberry Pi | |||
* Copyright (c) 2012-2015 Gordon Henderson | |||
* Copyright (c) 2012-2017 Gordon Henderson | |||
* Additional code for pwmSetClock by Chris Hall <chris@kchall.plus.com> | |||
* | |||
* Thanks to code samples from Gert Jan van Loo and the | |||
@@ -75,6 +75,7 @@ | |||
#include "softTone.h" | |||
#include "wiringPi.h" | |||
#include "../version.h" | |||
// Environment Variables | |||
@@ -129,9 +130,8 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ; | |||
// that I can find )-: | |||
// | |||
// Updates in September 2015 - all now static variables (and apologies for the caps) | |||
// due to the Pi v2 and the new /dev/gpiomem interface | |||
// due to the Pi v2, v3, etc. and the new /dev/gpiomem interface | |||
static volatile unsigned int RASPBERRY_PI_PERI_BASE ; | |||
static volatile unsigned int GPIO_PADS ; | |||
static volatile unsigned int GPIO_CLOCK_BASE ; | |||
static volatile unsigned int GPIO_BASE ; | |||
@@ -197,13 +197,18 @@ static volatile uint32_t *timer ; | |||
static volatile uint32_t *timerIrqRaw ; | |||
#endif | |||
// Data for use with the boardId functions. | |||
// The order of entries here to correspond with the PI_MODEL_X | |||
// and PI_VERSION_X defines in wiringPi.h | |||
// Only intended for the gpio command - use at your own risk! | |||
static int piModel2 = FALSE ; | |||
// piGpioBase: | |||
// The base address of the GPIO memory mapped hardware IO | |||
#define GPIO_PERI_BASE_OLD 0x20000000 | |||
#define GPIO_PERI_BASE_NEW 0x3F000000 | |||
static volatile unsigned int piGpioBase = 0 ; | |||
const char *piModelNames [16] = | |||
{ | |||
@@ -217,7 +222,7 @@ const char *piModelNames [16] = | |||
"Unknown07", // 07 | |||
"Pi 3", // 08 | |||
"Pi Zero", // 09 | |||
"Unknown10", // 10 | |||
"CM3", // 10 | |||
"Unknown11", // 11 | |||
"Unknown12", // 12 | |||
"Unknown13", // 13 | |||
@@ -649,7 +654,7 @@ int wiringPiFailure (int fatal, const char *message, ...) | |||
/* | |||
* piBoardRev: | |||
* piGpioLayout: | |||
* Return a number representing the hardware revision of the board. | |||
* This is not strictly the board revision but is used to check the | |||
* layout of the GPIO connector - and there are 2 types that we are | |||
@@ -666,30 +671,34 @@ int wiringPiFailure (int fatal, const char *message, ...) | |||
* 3 GPIO pins on the (original) 26-way header - BCM_GPIO 22 was dropped and | |||
* replaced with 27, and 0 + 1 - I2C bus 0 was changed to 2 + 3; I2C bus 1. | |||
* | |||
* Additionally, here we set the piModel2 flag too. This is again, nothing to | |||
* do with the actual model, but the major version numbers - the GPIO base | |||
* hardware address changed at model 2 and above (not the Zero though) | |||
* | |||
********************************************************************************* | |||
*/ | |||
static void piBoardRevOops (const char *why) | |||
static void piGpioLayoutOops (const char *why) | |||
{ | |||
fprintf (stderr, "piBoardRev: Unable to determine board revision from /proc/cpuinfo\n") ; | |||
fprintf (stderr, "Oops: Unable to determine board revision from /proc/cpuinfo\n") ; | |||
fprintf (stderr, " -> %s\n", why) ; | |||
fprintf (stderr, " -> You may want to check:\n") ; | |||
fprintf (stderr, " -> http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ; | |||
fprintf (stderr, " -> You'd best google the error to find out why.\n") ; | |||
//fprintf (stderr, " -> http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
int piBoardRev (void) | |||
int piGpioLayout (void) | |||
{ | |||
FILE *cpuFd ; | |||
char line [120] ; | |||
char *c ; | |||
static int boardRev = -1 ; | |||
static int gpioLayout = -1 ; | |||
if (boardRev != -1) // No point checking twice | |||
return boardRev ; | |||
if (gpioLayout != -1) // No point checking twice | |||
return gpioLayout ; | |||
if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) | |||
piBoardRevOops ("Unable to open /proc/cpuinfo") ; | |||
piGpioLayoutOops ("Unable to open /proc/cpuinfo") ; | |||
// Start by looking for the Architecture to make sure we're really running | |||
// on a Pi. I'm getting fed-up with people whinging at me because | |||
@@ -700,23 +709,23 @@ int piBoardRev (void) | |||
break ; | |||
if (strncmp (line, "Hardware", 8) != 0) | |||
piBoardRevOops ("No hardware line") ; | |||
piGpioLayoutOops ("No \"Hardware\" line") ; | |||
if (wiringPiDebug) | |||
printf ("piboardRev: Hardware: %s\n", line) ; | |||
printf ("piGpioLayout: Hardware: %s\n", line) ; | |||
// See if it's BCM2708 or BCM2709 | |||
// See if it's BCM2708 or BCM2709 or the new BCM2835. | |||
if (strstr (line, "BCM2709") != NULL) // Pi v2 - no point doing anything more at this point | |||
{ | |||
piModel2 = TRUE ; | |||
fclose (cpuFd) ; | |||
return boardRev = 2 ; | |||
} | |||
else if (strstr (line, "BCM2708") == NULL) | |||
// OK. As of Kernel 4.8, we have BCM2835 only, regardless of model. | |||
// However I still want to check because it will trap the cheapskates and rip- | |||
// off merchants who want to use wiringPi on non-Raspberry Pi platforms - which | |||
// I do not support so don't email me your bleating whinges about anything | |||
// other than a genuine Raspberry Pi. | |||
if (! (strstr (line, "BCM2708") || strstr (line, "BCM2709") || strstr (line, "BCM2835"))) | |||
{ | |||
fprintf (stderr, "Unable to determine hardware version. I see: %s,\n", line) ; | |||
fprintf (stderr, " - expecting BCM2708 or BCM2709.\n") ; | |||
fprintf (stderr, " - expecting BCM2708, BCM2709 or BCM2835.\n") ; | |||
fprintf (stderr, "If this is a genuine Raspberry Pi then please report this\n") ; | |||
fprintf (stderr, "to projects@drogon.net. If this is not a Raspberry Pi then you\n") ; | |||
fprintf (stderr, "are on your own as wiringPi is designed to support the\n") ; | |||
@@ -724,8 +733,11 @@ int piBoardRev (void) | |||
exit (EXIT_FAILURE) ; | |||
} | |||
// Now do the rest of it as before - we just need to see if it's an older | |||
// Rev 1 as anything else is rev 2. | |||
// Right - we're Probably on a Raspberry Pi. Check the revision field for the real | |||
// hardware type | |||
// In-future, I ought to use the device tree as there are now Pi entries in | |||
// /proc/device-tree/ ... | |||
// but I'll leave that for the next revision. | |||
// Isolate the Revision line | |||
@@ -737,7 +749,7 @@ int piBoardRev (void) | |||
fclose (cpuFd) ; | |||
if (strncmp (line, "Revision", 8) != 0) | |||
piBoardRevOops ("No \"Revision\" line") ; | |||
piGpioLayoutOops ("No \"Revision\" line") ; | |||
// Chomp trailing CR/NL | |||
@@ -745,7 +757,7 @@ int piBoardRev (void) | |||
*c = 0 ; | |||
if (wiringPiDebug) | |||
printf ("piboardRev: Revision string: %s\n", line) ; | |||
printf ("piGpioLayout: Revision string: %s\n", line) ; | |||
// Scan to the first character of the revision number | |||
@@ -754,7 +766,7 @@ int piBoardRev (void) | |||
break ; | |||
if (*c != ':') | |||
piBoardRevOops ("Bogus \"Revision\" line (no colon)") ; | |||
piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ; | |||
// Chomp spaces | |||
@@ -763,47 +775,44 @@ int piBoardRev (void) | |||
++c ; | |||
if (!isxdigit (*c)) | |||
piBoardRevOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ; | |||
piGpioLayoutOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ; | |||
// Make sure its long enough | |||
if (strlen (c) < 4) | |||
piBoardRevOops ("Bogus revision line (too small)") ; | |||
// If you have overvolted the Pi, then it appears that the revision | |||
// has 100000 added to it! | |||
// The actual condition for it being set is: | |||
// (force_turbo || current_limit_override || temp_limit>85) && over_voltage>0 | |||
// This test is not correct for the new encoding scheme, so we'll remove it here as | |||
// we don't really need it at this point. | |||
/******************** | |||
if (wiringPiDebug) | |||
if (strlen (c) != 4) | |||
printf ("piboardRev: This Pi has/is (force_turbo || current_limit_override || temp_limit>85) && over_voltage>0\n") ; | |||
*******************/ | |||
piGpioLayoutOops ("Bogus revision line (too small)") ; | |||
// Isolate last 4 characters: | |||
// Isolate last 4 characters: (in-case of overvolting or new encoding scheme) | |||
c = c + strlen (c) - 4 ; | |||
if (wiringPiDebug) | |||
printf ("piboardRev: last4Chars are: \"%s\"\n", c) ; | |||
printf ("piGpioLayout: last4Chars are: \"%s\"\n", c) ; | |||
if ( (strcmp (c, "0002") == 0) || (strcmp (c, "0003") == 0)) | |||
boardRev = 1 ; | |||
gpioLayout = 1 ; | |||
else | |||
boardRev = 2 ; // Covers everything else from the B revision 2 to the B+, the Pi v2 and CM's. | |||
gpioLayout = 2 ; // Covers everything else from the B revision 2 to the B+, the Pi v2, v3, zero and CM's. | |||
if (wiringPiDebug) | |||
printf ("piBoardRev: Returning revision: %d\n", boardRev) ; | |||
printf ("piGpioLayoutOops: Returning revision: %d\n", gpioLayout) ; | |||
return boardRev ; | |||
return gpioLayout ; | |||
} | |||
/* | |||
* piBoardRev: | |||
* Deprecated, but does the same as piGpioLayout | |||
********************************************************************************* | |||
*/ | |||
int piBoardRev (void) | |||
{ | |||
return piGpioLayout () ; | |||
} | |||
/* | |||
* piBoardId: | |||
* Return the real details of the board we have. | |||
@@ -822,20 +831,32 @@ int piBoardRev (void) | |||
* 0003 - Model B, Rev 1.1, 256MB, Egoman, Fuses/D14 removed. | |||
* | |||
* Newer Pi's with remapped GPIO: | |||
* 0004 - Model B, Rev 2, 256MB, Sony | |||
* 0005 - Model B, Rev 2, 256MB, Qisda | |||
* 0006 - Model B, Rev 2, 256MB, Egoman | |||
* 0007 - Model A, Rev 2, 256MB, Egoman | |||
* 0008 - Model A, Rev 2, 256MB, Sony | |||
* 0009 - Model A, Rev 2, 256MB, Qisda | |||
* 000d - Model B, Rev 2, 512MB, Egoman (Red Pi, Blue Pi?) | |||
* 000e - Model B, Rev 2, 512MB, Sony | |||
* 000f - Model B, Rev 2, 512MB, Qisda | |||
* 0004 - Model B, Rev 1.2, 256MB, Sony | |||
* 0005 - Model B, Rev 1.2, 256MB, Egoman | |||
* 0006 - Model B, Rev 1.2, 256MB, Egoman | |||
* | |||
* 0007 - Model A, Rev 1.2, 256MB, Egoman | |||
* 0008 - Model A, Rev 1.2, 256MB, Sony | |||
* 0009 - Model A, Rev 1.2, 256MB, Egoman | |||
* | |||
* 000d - Model B, Rev 1.2, 512MB, Egoman (Red Pi, Blue Pi?) | |||
* 000e - Model B, Rev 1.2, 512MB, Sony | |||
* 000f - Model B, Rev 1.2, 512MB, Egoman | |||
* | |||
* 0010 - Model B+, Rev 1.2, 512MB, Sony | |||
* 0011 - Pi CM, Rev 1.2, 512MB, Sony | |||
* 0012 - Model A+ Rev 1.2, 256MB, Sony | |||
* 0014 - Pi CM, Rev 1.1, 512MB, Sony (Actual Revision might be different) | |||
* 0015 - Model A+ Rev 1.1, 256MB, Sony | |||
* 0013 - Model B+ Rev 1.2, 512MB, Embest | |||
* 0016 - Model B+ Rev 1.2, 512MB, Sony | |||
* 0019 - Model B+ Rev 1.2, 512MB, Egoman | |||
* | |||
* 0011 - Pi CM, Rev 1.1, 512MB, Sony | |||
* 0014 - Pi CM, Rev 1.1, 512MB, Embest | |||
* 0017 - Pi CM, Rev 1.1, 512MB, Sony | |||
* 001a - Pi CM, Rev 1.1, 512MB, Egoman | |||
* | |||
* 0012 - Model A+ Rev 1.1, 256MB, Sony | |||
* 0015 - Model A+ Rev 1.1, 512MB, Embest | |||
* 0018 - Model A+ Rev 1.1, 256MB, Sony | |||
* 001b - Model A+ Rev 1.1, 256MB, Egoman | |||
* | |||
* A small thorn is the olde style overvolting - that will add in | |||
* 1000000 | |||
@@ -870,10 +891,10 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
// Will deal with the properly later on - for now, lets just get it going... | |||
// unsigned int modelNum ; | |||
(void)piBoardRev () ; // Call this first to make sure all's OK. Don't care about the result. | |||
(void)piGpioLayout () ; // Call this first to make sure all's OK. Don't care about the result. | |||
if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) | |||
piBoardRevOops ("Unable to open /proc/cpuinfo") ; | |||
piGpioLayoutOops ("Unable to open /proc/cpuinfo") ; | |||
while (fgets (line, 120, cpuFd) != NULL) | |||
if (strncmp (line, "Revision", 8) == 0) | |||
@@ -882,7 +903,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
fclose (cpuFd) ; | |||
if (strncmp (line, "Revision", 8) != 0) | |||
piBoardRevOops ("No \"Revision\" line") ; | |||
piGpioLayoutOops ("No \"Revision\" line") ; | |||
// Chomp trailing CR/NL | |||
@@ -901,7 +922,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
break ; | |||
if (*c != ':') | |||
piBoardRevOops ("Bogus \"Revision\" line (no colon)") ; | |||
piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ; | |||
// Chomp spaces | |||
@@ -910,7 +931,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
++c ; | |||
if (!isxdigit (*c)) | |||
piBoardRevOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ; | |||
piGpioLayoutOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ; | |||
revision = (unsigned int)strtol (c, NULL, 16) ; // Hex number with no leading 0x | |||
@@ -935,7 +956,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
*warranty = bWarranty ; | |||
if (wiringPiDebug) | |||
printf ("piboardId: rev: %d, type: %d, proc: %d, mfg: %d, mem: %d, warranty: %d\n", | |||
printf ("piBoardId: rev: %d, type: %d, proc: %d, mfg: %d, mem: %d, warranty: %d\n", | |||
bRev, bType, bProc, bMfg, bMem, bWarranty) ; | |||
} | |||
else // Old way | |||
@@ -944,12 +965,12 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
printf ("piBoardId: Old Way: revision is: %s\n", c) ; | |||
if (!isdigit (*c)) | |||
piBoardRevOops ("Bogus \"Revision\" line (no digit at start of revision)") ; | |||
piGpioLayoutOops ("Bogus \"Revision\" line (no digit at start of revision)") ; | |||
// Make sure its long enough | |||
if (strlen (c) < 4) | |||
piBoardRevOops ("Bogus \"Revision\" line (not long enough)") ; | |||
piGpioLayoutOops ("Bogus \"Revision\" line (not long enough)") ; | |||
// If longer than 4, we'll assume it's been overvolted | |||
@@ -963,21 +984,34 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
/**/ if (strcmp (c, "0002") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0003") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0004") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0005") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 0 ; *maker = PI_MAKER_UNKNOWN ; } | |||
else if (strcmp (c, "0006") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0007") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0008") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; ; } | |||
else if (strcmp (c, "0009") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 0 ; *maker = PI_MAKER_UNKNOWN ; } | |||
else if (strcmp (c, "000d") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "000e") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "000f") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0004") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0005") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0006") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0007") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0008") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; ; } | |||
else if (strcmp (c, "0009") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "000d") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "000e") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "000f") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0010") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0011") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0012") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0013") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0014") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0015") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0013") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EMBEST ; } | |||
else if (strcmp (c, "0016") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0019") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0011") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0014") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EMBEST ; } | |||
else if (strcmp (c, "0017") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "001a") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0012") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0015") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EMBEST ; } | |||
else if (strcmp (c, "0018") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "001b") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else { *model = 0 ; *rev = 0 ; *mem = 0 ; *maker = 0 ; } | |||
} | |||
} | |||
@@ -1022,9 +1056,6 @@ void setPadDrive (int group, int value) | |||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
if ((group < 0) || (group > 2)) | |||
return ; | |||
@@ -1098,9 +1129,6 @@ void pwmSetRange (unsigned int range) | |||
{ | |||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
*(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ; | |||
*(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ; | |||
} | |||
@@ -1122,9 +1150,6 @@ void pwmSetClock (int divisor) | |||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
if (wiringPiDebug) | |||
printf ("Setting to: %d. Current: 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ; | |||
@@ -1177,9 +1202,6 @@ void gpioClockSet (int pin, int freq) | |||
else if (wiringPiMode != WPI_MODE_GPIO) | |||
return ; | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
divi = 19200000 / freq ; | |||
divr = 19200000 % freq ; | |||
divf = (int)((double)divr * 4096.0 / 19200000.0) ; | |||
@@ -1222,13 +1244,13 @@ struct wiringPiNodeStruct *wiringPiFindNode (int pin) | |||
********************************************************************************* | |||
*/ | |||
static void pinModeDummy (struct wiringPiNodeStruct *node, int pin, int mode) { return ; } | |||
static void pullUpDnControlDummy (struct wiringPiNodeStruct *node, int pin, int pud) { return ; } | |||
static int digitalReadDummy (struct wiringPiNodeStruct *node, int pin) { return LOW ; } | |||
static void digitalWriteDummy (struct wiringPiNodeStruct *node, int pin, int value) { return ; } | |||
static void pwmWriteDummy (struct wiringPiNodeStruct *node, int pin, int value) { return ; } | |||
static int analogReadDummy (struct wiringPiNodeStruct *node, int pin) { return 0 ; } | |||
static void analogWriteDummy (struct wiringPiNodeStruct *node, int pin, int value) { return ; } | |||
static void pinModeDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int mode) { return ; } | |||
static void pullUpDnControlDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int pud) { return ; } | |||
static int digitalReadDummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return LOW ; } | |||
static void digitalWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } | |||
static void pwmWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } | |||
static int analogReadDummy (UNU struct wiringPiNodeStruct *node, UNU int pin) { return 0 ; } | |||
static void analogWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } | |||
struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) | |||
{ | |||
@@ -1352,17 +1374,11 @@ void pinMode (int pin, int mode) | |||
softToneCreate (origPin) ; | |||
else if (mode == PWM_TONE_OUTPUT) | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
pinMode (origPin, PWM_OUTPUT) ; // Call myself to enable PWM mode | |||
pwmSetMode (PWM_MODE_MS) ; | |||
} | |||
else if (mode == PWM_OUTPUT) | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin | |||
return ; | |||
@@ -1377,9 +1393,6 @@ void pinMode (int pin, int mode) | |||
} | |||
else if (mode == GPIO_CLOCK) | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
if ((alt = gpioToGpClkALT0 [pin]) == 0) // Not a GPIO_CLOCK pin | |||
return ; | |||
@@ -1534,9 +1547,6 @@ void pwmWrite (int pin, int value) | |||
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
/**/ if (wiringPiMode == WPI_MODE_PINS) | |||
pin = pinToGpio [pin] ; | |||
else if (wiringPiMode == WPI_MODE_PHYS) | |||
@@ -1603,9 +1613,6 @@ void pwmToneWrite (int pin, int freq) | |||
{ | |||
int range ; | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
if (freq == 0) | |||
pwmWrite (pin, 0) ; // Off | |||
else | |||
@@ -1630,7 +1637,7 @@ void pwmToneWrite (int pin, int freq) | |||
* Reading is just bit fiddling. | |||
* These are wiringPi pin numbers 0..7, or BCM_GPIO pin numbers | |||
* 17, 18, 22, 23, 24, 24, 4 on a Pi v1 rev 0-3 | |||
* 17, 18, 27, 23, 24, 24, 4 on a Pi v1 rev 3 onwards or B+, 2, zero | |||
* 17, 18, 27, 23, 24, 24, 4 on a Pi v1 rev 3 onwards or B+, 2, 3, zero | |||
********************************************************************************* | |||
*/ | |||
@@ -1720,8 +1727,8 @@ void digitalWriteByte2 (const int value) | |||
} | |||
else | |||
{ | |||
*(gpio + gpioToGPCLR [0]) = 0x0FF00000 ; | |||
*(gpio + gpioToGPSET [0]) = (value & 0xFF) << 20 ; | |||
*(gpio + gpioToGPCLR [0]) = (~value & 0xFF) << 20 ; // 0x0FF00000; ILJ > CHANGE: Old causes glitch | |||
*(gpio + gpioToGPSET [0]) = ( value & 0xFF) << 20 ; | |||
} | |||
} | |||
@@ -1772,18 +1779,20 @@ int waitForInterrupt (int pin, int mS) | |||
// Setup poll structure | |||
polls.fd = fd ; | |||
polls.events = POLLPRI ; // Urgent data! | |||
polls.events = POLLPRI | POLLERR ; | |||
// Wait for it ... | |||
x = poll (&polls, 1, mS) ; | |||
// Do a dummy read to clear the interrupt | |||
// If no error, do a dummy read to clear the interrupt | |||
// A one character read appars to be enough. | |||
// Followed by a seek to reset it. | |||
(void)read (fd, &c, 1) ; | |||
lseek (fd, 0, SEEK_SET) ; | |||
if (x > 0) | |||
{ | |||
lseek (fd, 0, SEEK_SET) ; // Rewind | |||
(void)read (fd, &c, 1) ; // Read & clear | |||
} | |||
return x ; | |||
} | |||
@@ -1797,7 +1806,7 @@ int waitForInterrupt (int pin, int mS) | |||
********************************************************************************* | |||
*/ | |||
static void *interruptHandler (void *arg) | |||
static void *interruptHandler (UNU void *arg) | |||
{ | |||
int myPin ; | |||
@@ -1922,11 +1931,19 @@ int wiringPiISR (int pin, int mode, void (*function)(void)) | |||
static void initialiseEpoch (void) | |||
{ | |||
#ifdef OLD_WAY | |||
struct timeval tv ; | |||
gettimeofday (&tv, NULL) ; | |||
epochMilli = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ; | |||
epochMicro = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)(tv.tv_usec) ; | |||
#else | |||
struct timespec ts ; | |||
clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ; | |||
epochMilli = (uint64_t)ts.tv_sec * (uint64_t)1000 + (uint64_t)(ts.tv_nsec / 1000000L) ; | |||
epochMicro = (uint64_t)ts.tv_sec * (uint64_t)1000000 + (uint64_t)(ts.tv_nsec / 1000L) ; | |||
#endif | |||
} | |||
@@ -2000,17 +2017,27 @@ void delayMicroseconds (unsigned int howLong) | |||
/* | |||
* millis: | |||
* Return a number of milliseconds as an unsigned int. | |||
* Wraps at 49 days. | |||
********************************************************************************* | |||
*/ | |||
unsigned int millis (void) | |||
{ | |||
struct timeval tv ; | |||
uint64_t now ; | |||
#ifdef OLD_WAY | |||
struct timeval tv ; | |||
gettimeofday (&tv, NULL) ; | |||
now = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ; | |||
#else | |||
struct timespec ts ; | |||
clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ; | |||
now = (uint64_t)ts.tv_sec * (uint64_t)1000 + (uint64_t)(ts.tv_nsec / 1000000L) ; | |||
#endif | |||
return (uint32_t)(now - epochMilli) ; | |||
} | |||
@@ -2018,20 +2045,41 @@ unsigned int millis (void) | |||
/* | |||
* micros: | |||
* Return a number of microseconds as an unsigned int. | |||
* Wraps after 71 minutes. | |||
********************************************************************************* | |||
*/ | |||
unsigned int micros (void) | |||
{ | |||
struct timeval tv ; | |||
uint64_t now ; | |||
#ifdef OLD_WAY | |||
struct timeval tv ; | |||
gettimeofday (&tv, NULL) ; | |||
now = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)tv.tv_usec ; | |||
#else | |||
struct timespec ts ; | |||
clock_gettime (CLOCK_MONOTONIC_RAW, &ts) ; | |||
now = (uint64_t)ts.tv_sec * (uint64_t)1000000 + (uint64_t)(ts.tv_nsec / 1000) ; | |||
#endif | |||
return (uint32_t)(now - epochMicro) ; | |||
} | |||
/* | |||
* wiringPiVersion: | |||
* Return our current version number | |||
********************************************************************************* | |||
*/ | |||
void wiringPiVersion (int *major, int *minor) | |||
{ | |||
*major = VERSION_MAJOR ; | |||
*minor = VERSION_MINOR ; | |||
} | |||
/* | |||
* wiringPiSetup: | |||
@@ -2047,18 +2095,17 @@ unsigned int micros (void) | |||
int wiringPiSetup (void) | |||
{ | |||
int fd ; | |||
int boardRev ; | |||
int model, rev, mem, maker, overVolted ; | |||
static int alreadyCalled = FALSE ; | |||
// This is here to trap the unwary - those who's program appears to work then fails some | |||
// time later with a weird error message because you run out of file-handles. | |||
static int alreadyDoneThis = FALSE ; | |||
if (alreadyCalled) | |||
(void)wiringPiFailure (WPI_FATAL, "wiringPiSetup*: You must only call this once per program run. This is a fatal error. Please fix your code.\n") ; | |||
// It's actually a fatal error to call any of the wiringPiSetup routines more than once, | |||
// (you run out of file handles!) but I'm fed-up with the useless twats who email | |||
// me bleating that there is a bug in my code, so screw-em. | |||
alreadyCalled = TRUE ; | |||
if (alreadyDoneThis) | |||
return 0 ; | |||
alreadyDoneThis = TRUE ; | |||
if (getenv (ENV_DEBUG) != NULL) | |||
wiringPiDebug = TRUE ; | |||
@@ -2066,101 +2113,99 @@ int wiringPiSetup (void) | |||
if (getenv (ENV_CODES) != NULL) | |||
wiringPiReturnCodes = TRUE ; | |||
if (getenv (ENV_GPIOMEM) != NULL) | |||
wiringPiTryGpioMem = TRUE ; | |||
if (wiringPiDebug) | |||
{ | |||
printf ("wiringPi: wiringPiSetup called\n") ; | |||
if (wiringPiTryGpioMem) | |||
printf ("wiringPi: Using /dev/gpiomem\n") ; | |||
} | |||
boardRev = piBoardRev () ; | |||
// Get the board ID information. We're not really using the information here, | |||
// but it will give us information like the GPIO layout scheme (2 variants | |||
// on the older 26-pin Pi's) and the GPIO peripheral base address. | |||
// and if we're running on a compute module, then wiringPi pin numbers | |||
// don't really many anything, so force native BCM mode anyway. | |||
/**/ if (boardRev == 1) // A, B, Rev 1, 1.1 | |||
piBoardId (&model, &rev, &mem, &maker, &overVolted) ; | |||
if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3)) | |||
wiringPiMode = WPI_MODE_GPIO ; | |||
else | |||
wiringPiMode = WPI_MODE_PINS ; | |||
/**/ if (piGpioLayout () == 1) // A, B, Rev 1, 1.1 | |||
{ | |||
pinToGpio = pinToGpioR1 ; | |||
physToGpio = physToGpioR1 ; | |||
} | |||
else // A, B, Rev 2, B+, CM, Pi2, Zero | |||
else // A2, B2, A+, B+, CM, Pi2, Pi3, Zero | |||
{ | |||
pinToGpio = pinToGpioR2 ; | |||
physToGpio = physToGpioR2 ; | |||
} | |||
// Note that a Zero is a model 1 | |||
if (piModel2) | |||
RASPBERRY_PI_PERI_BASE = 0x3F000000 ; | |||
else | |||
RASPBERRY_PI_PERI_BASE = 0x20000000 ; | |||
// Open the master /dev/ memory control device | |||
// See if /dev/gpiomem exists and we can open it... | |||
// ... | |||
if (wiringPiTryGpioMem) | |||
switch (model) | |||
{ | |||
if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/gpiomem: %s\n", strerror (errno)) ; | |||
RASPBERRY_PI_PERI_BASE = 0 ; | |||
case PI_MODEL_A: case PI_MODEL_B: | |||
case PI_MODEL_AP: case PI_MODEL_BP: | |||
case PI_ALPHA: case PI_MODEL_CM: case PI_MODEL_ZERO: | |||
piGpioBase = GPIO_PERI_BASE_OLD ; | |||
break ; | |||
default: | |||
piGpioBase = GPIO_PERI_BASE_NEW ; | |||
break ; | |||
} | |||
// ... otherwise fall back to the original /dev/mem which requires root level access | |||
// Open the master /dev/ memory control device | |||
// Device strategy: December 2016: | |||
// Try /dev/mem. If that fails, then | |||
// try /dev/gpiomem. If that fails then game over. | |||
else | |||
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) | |||
{ | |||
// This check is here because people are too stupid to check for themselves or read | |||
// error messages. | |||
if (geteuid () != 0) | |||
(void)wiringPiFailure (WPI_FATAL, "wiringPiSetup: Must be root. (Did you forget sudo?)\n") ; | |||
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ; | |||
if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem or /dev/gpiomem: %s.\n Try running with sudo?\n", strerror (errno)) ; | |||
piGpioBase = 0 ; | |||
} | |||
// Set the offsets into the memory interface. | |||
GPIO_PADS = RASPBERRY_PI_PERI_BASE + 0x00100000 ; | |||
GPIO_CLOCK_BASE = RASPBERRY_PI_PERI_BASE + 0x00101000 ; | |||
GPIO_BASE = RASPBERRY_PI_PERI_BASE + 0x00200000 ; | |||
GPIO_TIMER = RASPBERRY_PI_PERI_BASE + 0x0000B000 ; | |||
GPIO_PWM = RASPBERRY_PI_PERI_BASE + 0x0020C000 ; | |||
GPIO_PADS = piGpioBase + 0x00100000 ; | |||
GPIO_CLOCK_BASE = piGpioBase + 0x00101000 ; | |||
GPIO_BASE = piGpioBase + 0x00200000 ; | |||
GPIO_TIMER = piGpioBase + 0x0000B000 ; | |||
GPIO_PWM = piGpioBase + 0x0020C000 ; | |||
// Map the individual hardware components | |||
// GPIO: | |||
gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ; | |||
if ((int32_t)gpio == -1) | |||
if (gpio == MAP_FAILED) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ; | |||
// PWM | |||
pwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PWM) ; | |||
if ((int32_t)pwm == -1) | |||
if (pwm == MAP_FAILED) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PWM) failed: %s\n", strerror (errno)) ; | |||
// Clock control (needed for PWM) | |||
clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_BASE) ; | |||
if ((int32_t)clk == -1) | |||
if (clk == MAP_FAILED) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ; | |||
// The drive pads | |||
pads = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PADS) ; | |||
if ((int32_t)pads == -1) | |||
if (pads == MAP_FAILED) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PADS) failed: %s\n", strerror (errno)) ; | |||
#ifdef USE_TIMER | |||
// The system timer | |||
timer = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_TIMER) ; | |||
if ((int32_t)timer == -1) | |||
if (timer == MAP_FAILED) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (TIMER) failed: %s\n", strerror (errno)) ; | |||
// Set the timer to free-running, 1MHz. | |||
@@ -2174,14 +2219,6 @@ int wiringPiSetup (void) | |||
initialiseEpoch () ; | |||
// If we're running on a compute module, then wiringPi pin numbers don't really many anything... | |||
piBoardId (&model, &rev, &mem, &maker, &overVolted) ; | |||
if (model == PI_MODEL_CM) | |||
wiringPiMode = WPI_MODE_GPIO ; | |||
else | |||
wiringPiMode = WPI_MODE_PINS ; | |||
return 0 ; | |||
} | |||
@@ -2241,18 +2278,19 @@ int wiringPiSetupPhys (void) | |||
int wiringPiSetupSys (void) | |||
{ | |||
int boardRev ; | |||
int pin ; | |||
char fName [128] ; | |||
static int alreadyCalled = FALSE ; | |||
// This is here to trap the unwary - those who's program appears to work then fails some | |||
// time later with a weird error message because you run out of file-handles. | |||
static int alreadyDoneThis = FALSE ; | |||
if (alreadyCalled) | |||
(void)wiringPiFailure (WPI_FATAL, "wiringPiSetupSys: You must only call this once per program run. This is a fatal error. Please fix your code.\n") ; | |||
// It's actually a fatal error to call any of the wiringPiSetup routines more than once, | |||
// (you run out of file handles!) but I'm fed-up with the useless twats who email | |||
// me bleating that there is a bug in my code, so screw-em. | |||
alreadyCalled = TRUE ; | |||
if (alreadyDoneThis) | |||
return 0 ; | |||
alreadyDoneThis = TRUE ; | |||
if (getenv (ENV_DEBUG) != NULL) | |||
wiringPiDebug = TRUE ; | |||
@@ -2263,9 +2301,7 @@ int wiringPiSetupSys (void) | |||
if (wiringPiDebug) | |||
printf ("wiringPi: wiringPiSetupSys called\n") ; | |||
boardRev = piBoardRev () ; | |||
if (boardRev == 1) | |||
if (piGpioLayout () == 1) | |||
{ | |||
pinToGpio = pinToGpioR1 ; | |||
physToGpio = physToGpioR1 ; | |||
@@ -1,7 +1,7 @@ | |||
/* | |||
* wiringPi.h: | |||
* Arduino like Wiring library for the Raspberry Pi. | |||
* Copyright (c) 2012-2016 Gordon Henderson | |||
* Copyright (c) 2012-2017 Gordon Henderson | |||
*********************************************************************** | |||
* This file is part of wiringPi: | |||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | |||
@@ -32,6 +32,10 @@ | |||
# define FALSE (!TRUE) | |||
#endif | |||
// GCC warning suppressor | |||
#define UNU __attribute__((unused)) | |||
// Handy defines | |||
// wiringPi modes | |||
@@ -77,16 +81,17 @@ | |||
// Pi model types and version numbers | |||
// Intended for the GPIO program Use at your own risk. | |||
#define PI_MODEL_A 0 | |||
#define PI_MODEL_B 1 | |||
#define PI_MODEL_AP 2 | |||
#define PI_MODEL_BP 3 | |||
#define PI_MODEL_2 4 | |||
#define PI_ALPHA 5 | |||
#define PI_MODEL_CM 6 | |||
#define PI_MODEL_07 7 | |||
#define PI_MODEL_3 8 | |||
#define PI_MODEL_ZERO 9 | |||
#define PI_MODEL_A 0 | |||
#define PI_MODEL_B 1 | |||
#define PI_MODEL_AP 2 | |||
#define PI_MODEL_BP 3 | |||
#define PI_MODEL_2 4 | |||
#define PI_ALPHA 5 | |||
#define PI_MODEL_CM 6 | |||
#define PI_MODEL_07 7 | |||
#define PI_MODEL_3 8 | |||
#define PI_MODEL_ZERO 9 | |||
#define PI_MODEL_CM3 10 | |||
#define PI_VERSION_1 0 | |||
#define PI_VERSION_1_1 1 | |||
@@ -95,7 +100,7 @@ | |||
#define PI_MAKER_SONY 0 | |||
#define PI_MAKER_EGOMAN 1 | |||
#define PI_MAKER_MBEST 2 | |||
#define PI_MAKER_EMBEST 2 | |||
#define PI_MAKER_UNKNOWN 3 | |||
extern const char *piModelNames [16] ; | |||
@@ -108,7 +113,7 @@ extern const int piMemorySize [ 8] ; | |||
// Threads | |||
#define PI_THREAD(X) void *X (void *dummy) | |||
#define PI_THREAD(X) void *X (UNU void *dummy) | |||
// Failure modes | |||
@@ -168,6 +173,7 @@ extern int wiringPiFailure (int fatal, const char *message, ...) ; | |||
extern struct wiringPiNodeStruct *wiringPiFindNode (int pin) ; | |||
extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) ; | |||
extern void wiringPiVersion (int *major, int *minor) ; | |||
extern int wiringPiSetup (void) ; | |||
extern int wiringPiSetupSys (void) ; | |||
extern int wiringPiSetupGpio (void) ; | |||
@@ -190,7 +196,8 @@ extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio | |||
// On-Board Raspberry Pi hardware specific stuff | |||
extern int piBoardRev (void) ; | |||
extern int piGpioLayout (void) ; | |||
extern int piBoardRev (void) ; // Deprecated | |||
extern void piBoardId (int *model, int *rev, int *mem, int *maker, int *overVolted) ; | |||
extern int wpiPinToGpio (int wpiPin) ; | |||
extern int physPinToGpio (int physPin) ; | |||
@@ -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" ; | |||
@@ -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] ; | |||
@@ -49,24 +49,36 @@ int serialOpen (const char *device, const int baud) | |||
switch (baud) | |||
{ | |||
case 50: myBaud = B50 ; break ; | |||
case 75: myBaud = B75 ; break ; | |||
case 110: myBaud = B110 ; break ; | |||
case 134: myBaud = B134 ; break ; | |||
case 150: myBaud = B150 ; break ; | |||
case 200: myBaud = B200 ; break ; | |||
case 300: myBaud = B300 ; break ; | |||
case 600: myBaud = B600 ; break ; | |||
case 1200: myBaud = B1200 ; break ; | |||
case 1800: myBaud = B1800 ; break ; | |||
case 2400: myBaud = B2400 ; break ; | |||
case 4800: myBaud = B4800 ; break ; | |||
case 9600: myBaud = B9600 ; break ; | |||
case 19200: myBaud = B19200 ; break ; | |||
case 38400: myBaud = B38400 ; break ; | |||
case 57600: myBaud = B57600 ; break ; | |||
case 115200: myBaud = B115200 ; break ; | |||
case 230400: myBaud = B230400 ; break ; | |||
case 50: myBaud = B50 ; break ; | |||
case 75: myBaud = B75 ; break ; | |||
case 110: myBaud = B110 ; break ; | |||
case 134: myBaud = B134 ; break ; | |||
case 150: myBaud = B150 ; break ; | |||
case 200: myBaud = B200 ; break ; | |||
case 300: myBaud = B300 ; break ; | |||
case 600: myBaud = B600 ; break ; | |||
case 1200: myBaud = B1200 ; break ; | |||
case 1800: myBaud = B1800 ; break ; | |||
case 2400: myBaud = B2400 ; break ; | |||
case 4800: myBaud = B4800 ; break ; | |||
case 9600: myBaud = B9600 ; break ; | |||
case 19200: myBaud = B19200 ; break ; | |||
case 38400: myBaud = B38400 ; break ; | |||
case 57600: myBaud = B57600 ; break ; | |||
case 115200: myBaud = B115200 ; break ; | |||
case 230400: myBaud = B230400 ; break ; | |||
case 460800: myBaud = B460800 ; break ; | |||
case 500000: myBaud = B500000 ; break ; | |||
case 576000: myBaud = B576000 ; break ; | |||
case 921600: myBaud = B921600 ; break ; | |||
case 1000000: myBaud = B1000000 ; break ; | |||
case 1152000: myBaud = B1152000 ; break ; | |||
case 1500000: myBaud = B1500000 ; break ; | |||
case 2000000: myBaud = B2000000 ; break ; | |||
case 2500000: myBaud = B2500000 ; break ; | |||
case 3000000: myBaud = B3000000 ; break ; | |||
case 3500000: myBaud = B3500000 ; break ; | |||
case 4000000: myBaud = B4000000 ; break ; | |||
default: | |||
return -2 ; | |||
@@ -96,7 +108,7 @@ int serialOpen (const char *device, const int baud) | |||
options.c_cc [VMIN] = 0 ; | |||
options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds) | |||
tcsetattr (fd, TCSANOW | TCSAFLUSH, &options) ; | |||
tcsetattr (fd, TCSANOW, &options) ; | |||
ioctl (fd, TIOCMGET, &status); | |||
@@ -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" | |||
@@ -429,6 +433,69 @@ static int doExtensionPcf8591 (char *progName, int pinBase, char *params) | |||
/* | |||
* doExtensionPseudoPins: | |||
* 64 Memory resident pseudo pins | |||
* pseudoPins:base | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionPseudoPins (UNU char *progName, int pinBase, UNU char *params) | |||
{ | |||
pseudoPinsSetup (pinBase) ; | |||
return TRUE ; | |||
} | |||
/* | |||
* doExtensionBmp180: | |||
* Analog Temp + Pressure | |||
* bmp180:base | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionBmp180 (UNU char *progName, int pinBase, UNU char *params) | |||
{ | |||
bmp180Setup (pinBase) ; | |||
return TRUE ; | |||
} | |||
/* | |||
* doExtensionHtu21d: | |||
* Analog humidity + Pressure | |||
* htu21d:base | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionHtu21d (UNU char *progName, int pinBase, UNU char *params) | |||
{ | |||
htu21dSetup (pinBase) ; | |||
return TRUE ; | |||
} | |||
/* | |||
* doExtensionDs18b20: | |||
* 1-Wire Temperature | |||
* htu21d:base:serialNum | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionDs18b20 (char *progName, int pinBase, char *params) | |||
{ | |||
char *serialNum ; | |||
if ((params = extractStr (progName, params, &serialNum)) == NULL) | |||
return FALSE ; | |||
return ds18b20Setup (pinBase, serialNum) ; | |||
} | |||
/* | |||
* doExtensionMax31855: | |||
* Analog IO | |||
* max31855:base:spiChan | |||
@@ -565,7 +632,7 @@ static int doExtensionMcp4802 (char *progName, int pinBase, char *params) | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionSn3218 (char *progName, int pinBase, char *params) | |||
static int doExtensionSn3218 (UNU char *progName, int pinBase, UNU char *params) | |||
{ | |||
sn3218Setup (pinBase) ; | |||
return TRUE ; | |||
@@ -677,6 +744,10 @@ static struct extensionFunctionStruct extensionFunctions [] = | |||
{ "sr595", &doExtensionSr595 }, | |||
{ "pcf8574", &doExtensionPcf8574 }, | |||
{ "pcf8591", &doExtensionPcf8591 }, | |||
{ "bmp180", &doExtensionBmp180 }, | |||
{ "pseudoPins", &doExtensionPseudoPins }, | |||
{ "htu21d", &doExtensionHtu21d }, | |||
{ "ds18b20", &doExtensionDs18b20 }, | |||
{ "mcp3002", &doExtensionMcp3002 }, | |||
{ "mcp3004", &doExtensionMcp3004 }, | |||
{ "mcp4802", &doExtensionMcp4802 }, | |||