for kernels 4.8 onwards. Some very old stuff might break. Additional fixes for the ISR code and some tweaks here and there. I've removed the checks for some operations that might fail when using the gpiomem interface - which is now the default way of doing things - if your program segfaults, then you may need to use sudo on it.pull/62/head
@@ -1 +1 @@ | |||
2.32 | |||
2.36 |
@@ -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.36 | |||
Section: libraries | |||
Priority: optional | |||
Architecture: armhf | |||
@@ -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: | |||
@@ -57,6 +57,8 @@ extern void doPins (void) ; | |||
#define PI_USB_POWER_CONTROL 38 | |||
#define I2CDETECT "/usr/sbin/i2cdetect" | |||
#define MODPROBE "/sbin/modprobe" | |||
#define RMMOD "/sbin/rmmod" | |||
int wpMode ; | |||
@@ -65,6 +67,7 @@ char *usage = "Usage: gpio -v\n" | |||
" gpio [-g|-1] [-x extension:params] ...\n" | |||
" gpio [-p] <read/write/wb> ...\n" | |||
" gpio <read/write/aread/awritewb/pwm/clock/mode> ...\n" | |||
" gpio <toggle/blink> <pin>\n" | |||
" gpio readall/reset\n" | |||
" gpio unexportall/exports\n" | |||
" gpio export/edge/unexport ...\n" | |||
@@ -76,6 +79,8 @@ char *usage = "Usage: gpio -v\n" | |||
" gpio load spi/i2c\n" | |||
" gpio unload spi/i2c\n" | |||
" gpio i2cd/i2cdetect\n" | |||
" gpio rbx/rbd\n" | |||
" gpio wb <value>\n" | |||
" gpio usbp high/low\n" | |||
" gpio gbr <channel>\n" | |||
" gpio gbw <channel> <value>" ; // No trailing newline needed here. | |||
@@ -103,6 +108,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 +274,18 @@ static void doLoad (int argc, char *argv []) | |||
else | |||
_doLoadUsage (argv) ; | |||
if (findExecutable ("modprobe") == NULL) | |||
printf ("No found\n") ; | |||
if (!moduleLoaded (module1)) | |||
{ | |||
sprintf (cmd, "/sbin/modprobe %s%s", module1, args1) ; | |||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module1, args1) ; | |||
system (cmd) ; | |||
} | |||
if (!moduleLoaded (module2)) | |||
{ | |||
sprintf (cmd, "/sbin/modprobe %s%s", module2, args2) ; | |||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module2, args2) ; | |||
system (cmd) ; | |||
} | |||
@@ -292,13 +339,13 @@ static void doUnLoad (int argc, char *argv []) | |||
if (moduleLoaded (module1)) | |||
{ | |||
sprintf (cmd, "/sbin/rmmod %s", module1) ; | |||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module1) ; | |||
system (cmd) ; | |||
} | |||
if (moduleLoaded (module2)) | |||
{ | |||
sprintf (cmd, "/sbin/rmmod %s", module2) ; | |||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module2) ; | |||
system (cmd) ; | |||
} | |||
} | |||
@@ -312,11 +359,10 @@ static void doUnLoad (int argc, char *argv []) | |||
static void doI2Cdetect (int argc, char *argv []) | |||
{ | |||
int port = piBoardRev () == 1 ? 0 : 1 ; | |||
char command [128] ; | |||
struct stat statBuf ; | |||
int port = piGpioLayout () == 1 ? 0 : 1 ; | |||
char *c, *command ; | |||
if (stat (I2CDETECT, &statBuf) < 0) | |||
if ((c = findExecutable (I2CDETECT)) == NULL) | |||
{ | |||
fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ; | |||
return ; | |||
@@ -328,7 +374,8 @@ static void doI2Cdetect (int argc, char *argv []) | |||
return ; | |||
} | |||
sprintf (command, "%s -y %d", I2CDETECT, port) ; | |||
command = malloc (strlen (c) + 16) ; | |||
sprintf (command, "%s -y %d", c, port) ; | |||
if (system (command) < 0) | |||
fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ; | |||
@@ -943,7 +990,7 @@ static void doAwrite (int argc, char *argv []) | |||
/* | |||
* doWriteByte: | |||
* gpio write value | |||
* gpio wb value | |||
********************************************************************************* | |||
*/ | |||
@@ -964,6 +1011,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 +1098,34 @@ void doToggle (int argc, char *argv []) | |||
/* | |||
* doBlink: | |||
* Blink an IO pin | |||
********************************************************************************* | |||
*/ | |||
void doBlink (int argc, char *argv []) | |||
{ | |||
int pin ; | |||
if (argc != 3) | |||
{ | |||
fprintf (stderr, "Usage: %s blink pin\n", argv [0]) ; | |||
exit (1) ; | |||
} | |||
pin = atoi (argv [2]) ; | |||
pinMode (pin, OUTPUT) ; | |||
for (;;) | |||
{ | |||
digitalWrite (pin, !digitalRead (pin)) ; | |||
delay (500) ; | |||
} | |||
} | |||
/* | |||
* doPwmTone: | |||
* Output a tone in a PWM pin | |||
********************************************************************************* | |||
@@ -1162,6 +1261,8 @@ static void doVersion (char *argv []) | |||
{ | |||
int model, rev, mem, maker, warranty ; | |||
struct stat statBuf ; | |||
char name [80] ; | |||
FILE *fd ; | |||
printf ("gpio version: %s\n", VERSION) ; | |||
printf ("Copyright (c) 2012-2015 Gordon Henderson\n") ; | |||
@@ -1179,12 +1280,18 @@ static void doVersion (char *argv []) | |||
if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ... | |||
printf (" * Device tree is enabled.\n") ; | |||
if (stat ("/dev/gpiomem", &statBuf) == 0) // User level GPIO is GO | |||
if (stat ("/proc/device-tree/model", &statBuf) == 0) // Output Kernel idea of board type | |||
{ | |||
printf (" * This Raspberry Pi supports user-level GPIO access.\n") ; | |||
printf (" -> See the man-page for more details\n") ; | |||
printf (" -> ie. export WIRINGPI_GPIOMEM=1\n") ; | |||
if ((fd = fopen ("/proc/device-tree/model", "r")) != NULL) | |||
{ | |||
fgets (name, 80, fd) ; | |||
fclose (fd) ; | |||
printf (" *--> %s\n", name) ; | |||
} | |||
} | |||
if (stat ("/dev/gpiomem", &statBuf) == 0) // User level GPIO is GO | |||
printf (" * This Raspberry Pi supports user-level GPIO access.\n") ; | |||
else | |||
printf (" * Root or sudo required for GPIO access.\n") ; | |||
} | |||
@@ -1225,7 +1332,7 @@ int main (int argc, char *argv []) | |||
if ((strcmp (argv [1], "-R") == 0) || (strcmp (argv [1], "-V") == 0)) | |||
{ | |||
printf ("%d\n", piBoardRev ()) ; | |||
printf ("%d\n", piGpioLayout ()) ; | |||
return 0 ; | |||
} | |||
@@ -1375,6 +1482,7 @@ int main (int argc, char *argv []) | |||
// GPIO Nicies | |||
else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle (argc, argv) ; | |||
else if (strcasecmp (argv [1], "blink" ) == 0) doBlink (argc, argv) ; | |||
// Pi Specifics | |||
@@ -1391,6 +1499,8 @@ int main (int argc, char *argv []) | |||
else if (strcasecmp (argv [1], "i2cd" ) == 0) doI2Cdetect (argc, argv) ; | |||
else if (strcasecmp (argv [1], "reset" ) == 0) doReset (argv [0]) ; | |||
else if (strcasecmp (argv [1], "wb" ) == 0) doWriteByte (argc, argv) ; | |||
else if (strcasecmp (argv [1], "rbx" ) == 0) doReadByte (argc, argv, TRUE) ; | |||
else if (strcasecmp (argv [1], "rbd" ) == 0) doReadByte (argc, argv, FALSE) ; | |||
else if (strcasecmp (argv [1], "clock" ) == 0) doClock (argc, argv) ; | |||
else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ; | |||
else | |||
@@ -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 | |||
@@ -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 ", | |||
@@ -5,7 +5,7 @@ | |||
# in-turn. | |||
################################################################################# | |||
# This file is part of wiringPi: | |||
# Wiring Compatable library for the Raspberry Pi | |||
# A "wiring" library for the Raspberry Pi | |||
# | |||
# wiringPi is free software: you can redistribute it and/or modify | |||
# it under the terms of the GNU Lesser General Public License as published by | |||
@@ -1 +1 @@ | |||
#define VERSION "2.32" | |||
#define VERSION "2.36" |
@@ -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 | |||
@@ -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/ . |
@@ -39,9 +39,9 @@ DEBUG = -O2 | |||
CC = gcc | |||
INCLUDE = -I. | |||
DEFS = -D_GNU_SOURCE | |||
CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Winline $(INCLUDE) -pipe -fPIC | |||
CFLAGS = $(DEBUG) $(DEFS) -Wformat=2 -Wall -Wextra -Winline $(INCLUDE) -pipe -fPIC | |||
LIBS = | |||
LIBS = -lm -lpthread -lrt | |||
############################################################################### | |||
@@ -57,23 +57,12 @@ SRC = wiringPi.c \ | |||
mcp3002.c mcp3004.c mcp4802.c mcp3422.c \ | |||
max31855.c max5322.c ads1115.c \ | |||
sn3218.c \ | |||
bmp180.c htu21d.c ds18b20.c \ | |||
drcSerial.c \ | |||
pseudoPins.c \ | |||
wpiExtensions.c | |||
HEADERS = wiringPi.h \ | |||
wiringSerial.h wiringShift.h \ | |||
wiringPiSPI.h wiringPiI2C.h \ | |||
softPwm.h softTone.h \ | |||
mcp23008.h mcp23016.h mcp23017.h \ | |||
mcp23s08.h mcp23s17.h \ | |||
sr595.h \ | |||
pcf8574.h pcf8591.h \ | |||
mcp3002.h mcp3004.h mcp4802.h mcp3422.h \ | |||
max31855.h max5322.h ads1115.h \ | |||
sn3218.h \ | |||
drcSerial.h \ | |||
wpiExtensions.h | |||
HEADERS = $(shell ls *.h) | |||
OBJ = $(SRC:.c=.o) | |||
@@ -89,7 +78,7 @@ $(STATIC): $(OBJ) | |||
$(DYNAMIC): $(OBJ) | |||
$Q echo "[Link (Dynamic)]" | |||
$Q $(CC) -shared -Wl,-soname,libwiringPi.so$(WIRINGPI_SONAME_SUFFIX) -o libwiringPi.so.$(VERSION) -lpthread $(OBJ) | |||
$Q $(CC) -shared -Wl,-soname,libwiringPi.so$(WIRINGPI_SONAME_SUFFIX) -o libwiringPi.so.$(VERSION) $(LIBS) $(OBJ) | |||
.c.o: | |||
$Q echo [Compile] $< | |||
@@ -174,9 +163,13 @@ mcp4802.o: wiringPi.h wiringPiSPI.h mcp4802.h | |||
mcp3422.o: wiringPi.h wiringPiI2C.h mcp3422.h | |||
max31855.o: wiringPi.h wiringPiSPI.h max31855.h | |||
max5322.o: wiringPi.h wiringPiSPI.h max5322.h | |||
ads1115.o: wiringPi.h wiringPiI2C.h ads1115.h | |||
sn3218.o: wiringPi.h wiringPiI2C.h sn3218.h | |||
bmp180.o: wiringPi.h wiringPiI2C.h bmp180.h | |||
htu21d.o: wiringPi.h wiringPiI2C.h htu21d.h | |||
ds18b20.o: wiringPi.h ds18b20.h | |||
drcSerial.o: wiringPi.h wiringSerial.h drcSerial.h | |||
wpiExtensions.o: wiringPi.h mcp23008.h mcp23016.h mcp23017.h mcp23s08.h | |||
wpiExtensions.o: mcp23s17.h sr595.h pcf8574.h pcf8591.h mcp3002.h mcp3004.h | |||
wpiExtensions.o: mcp4802.h mcp3422.h max31855.h max5322.h sn3218.h | |||
wpiExtensions.o: drcSerial.h wpiExtensions.h | |||
wpiExtensions.o: mcp4802.h mcp3422.h max31855.h max5322.h ads1115.h sn3218.h | |||
wpiExtensions.o: drcSerial.h bmp180.h htu21d.h ds18b20.h wpiExtensions.h |
@@ -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 (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 ; | |||
} | |||
@@ -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) ; | |||
@@ -129,9 +129,8 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ; | |||
// that I can find )-: | |||
// | |||
// Updates in September 2015 - all now static variables (and apologies for the caps) | |||
// due to the Pi v2 and the new /dev/gpiomem interface | |||
// due to the Pi v2, v3, etc. and the new /dev/gpiomem interface | |||
static volatile unsigned int RASPBERRY_PI_PERI_BASE ; | |||
static volatile unsigned int GPIO_PADS ; | |||
static volatile unsigned int GPIO_CLOCK_BASE ; | |||
static volatile unsigned int GPIO_BASE ; | |||
@@ -197,13 +196,23 @@ static volatile uint32_t *timer ; | |||
static volatile uint32_t *timerIrqRaw ; | |||
#endif | |||
// GCC warning suppressor | |||
#define UNU __attribute__((unused)) | |||
// Data for use with the boardId functions. | |||
// The order of entries here to correspond with the PI_MODEL_X | |||
// and PI_VERSION_X defines in wiringPi.h | |||
// Only intended for the gpio command - use at your own risk! | |||
static int piModel2 = FALSE ; | |||
// piGpioBase: | |||
// The base address of the GPIO memory mapped hardware IO | |||
#define GPIO_PERI_BASE_OLD 0x20000000 | |||
#define GPIO_PERI_BASE_NEW 0x3F000000 | |||
static volatile unsigned int piGpioBase = 0 ; | |||
const char *piModelNames [16] = | |||
{ | |||
@@ -649,7 +658,7 @@ int wiringPiFailure (int fatal, const char *message, ...) | |||
/* | |||
* piBoardRev: | |||
* piGpioLayout: | |||
* Return a number representing the hardware revision of the board. | |||
* This is not strictly the board revision but is used to check the | |||
* layout of the GPIO connector - and there are 2 types that we are | |||
@@ -666,30 +675,34 @@ int wiringPiFailure (int fatal, const char *message, ...) | |||
* 3 GPIO pins on the (original) 26-way header - BCM_GPIO 22 was dropped and | |||
* replaced with 27, and 0 + 1 - I2C bus 0 was changed to 2 + 3; I2C bus 1. | |||
* | |||
* Additionally, here we set the piModel2 flag too. This is again, nothing to | |||
* do with the actual model, but the major version numbers - the GPIO base | |||
* hardware address changed at model 2 and above (not the Zero though) | |||
* | |||
********************************************************************************* | |||
*/ | |||
static void piBoardRevOops (const char *why) | |||
static void piGpioLayoutOops (const char *why) | |||
{ | |||
fprintf (stderr, "piBoardRev: Unable to determine board revision from /proc/cpuinfo\n") ; | |||
fprintf (stderr, "Oops: Unable to determine board revision from /proc/cpuinfo\n") ; | |||
fprintf (stderr, " -> %s\n", why) ; | |||
fprintf (stderr, " -> You may want to check:\n") ; | |||
fprintf (stderr, " -> http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ; | |||
fprintf (stderr, " -> You'd best google the error to find out why.\n") ; | |||
//fprintf (stderr, " -> http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ; | |||
exit (EXIT_FAILURE) ; | |||
} | |||
int piBoardRev (void) | |||
int piGpioLayout (void) | |||
{ | |||
FILE *cpuFd ; | |||
char line [120] ; | |||
char *c ; | |||
static int boardRev = -1 ; | |||
static int gpioLayout = -1 ; | |||
if (boardRev != -1) // No point checking twice | |||
return boardRev ; | |||
if (gpioLayout != -1) // No point checking twice | |||
return gpioLayout ; | |||
if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) | |||
piBoardRevOops ("Unable to open /proc/cpuinfo") ; | |||
piGpioLayoutOops ("Unable to open /proc/cpuinfo") ; | |||
// Start by looking for the Architecture to make sure we're really running | |||
// on a Pi. I'm getting fed-up with people whinging at me because | |||
@@ -700,23 +713,23 @@ int piBoardRev (void) | |||
break ; | |||
if (strncmp (line, "Hardware", 8) != 0) | |||
piBoardRevOops ("No hardware line") ; | |||
piGpioLayoutOops ("No \"Hardware\" line") ; | |||
if (wiringPiDebug) | |||
printf ("piboardRev: Hardware: %s\n", line) ; | |||
printf ("piGpioLayout: Hardware: %s\n", line) ; | |||
// See if it's BCM2708 or BCM2709 | |||
// See if it's BCM2708 or BCM2709 or the new BCM2835. | |||
if (strstr (line, "BCM2709") != NULL) // Pi v2 - no point doing anything more at this point | |||
{ | |||
piModel2 = TRUE ; | |||
fclose (cpuFd) ; | |||
return boardRev = 2 ; | |||
} | |||
else if (strstr (line, "BCM2708") == NULL) | |||
// OK. As of Kernel 4.8, we have BCM2835 only, regardless of model. | |||
// However I still want to check because it will trap the cheapskates and rip- | |||
// off merchants who want to use wiringPi on non-Raspberry Pi platforms - which | |||
// I do not support so don't email me your bleating whinges about anything | |||
// other than a genuine Raspberry Pi. | |||
if (! (strstr (line, "BCM2708") || strstr (line, "BCM2709") || strstr (line, "BCM2835"))) | |||
{ | |||
fprintf (stderr, "Unable to determine hardware version. I see: %s,\n", line) ; | |||
fprintf (stderr, " - expecting BCM2708 or BCM2709.\n") ; | |||
fprintf (stderr, " - expecting BCM2708, BCM2709 or BCM2835.\n") ; | |||
fprintf (stderr, "If this is a genuine Raspberry Pi then please report this\n") ; | |||
fprintf (stderr, "to projects@drogon.net. If this is not a Raspberry Pi then you\n") ; | |||
fprintf (stderr, "are on your own as wiringPi is designed to support the\n") ; | |||
@@ -724,8 +737,11 @@ int piBoardRev (void) | |||
exit (EXIT_FAILURE) ; | |||
} | |||
// Now do the rest of it as before - we just need to see if it's an older | |||
// Rev 1 as anything else is rev 2. | |||
// Right - we're Probably on a Raspberry Pi. Check the revision field for the real | |||
// hardware type | |||
// In-future, I ought to use the device tree as there are now Pi entries in | |||
// /proc/device-tree/ ... | |||
// but I'll leave that for the next revision. | |||
// Isolate the Revision line | |||
@@ -737,7 +753,7 @@ int piBoardRev (void) | |||
fclose (cpuFd) ; | |||
if (strncmp (line, "Revision", 8) != 0) | |||
piBoardRevOops ("No \"Revision\" line") ; | |||
piGpioLayoutOops ("No \"Revision\" line") ; | |||
// Chomp trailing CR/NL | |||
@@ -745,7 +761,7 @@ int piBoardRev (void) | |||
*c = 0 ; | |||
if (wiringPiDebug) | |||
printf ("piboardRev: Revision string: %s\n", line) ; | |||
printf ("piGpioLayout: Revision string: %s\n", line) ; | |||
// Scan to the first character of the revision number | |||
@@ -754,7 +770,7 @@ int piBoardRev (void) | |||
break ; | |||
if (*c != ':') | |||
piBoardRevOops ("Bogus \"Revision\" line (no colon)") ; | |||
piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ; | |||
// Chomp spaces | |||
@@ -763,46 +779,46 @@ int piBoardRev (void) | |||
++c ; | |||
if (!isxdigit (*c)) | |||
piBoardRevOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ; | |||
piGpioLayoutOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ; | |||
// Make sure its long enough | |||
if (strlen (c) < 4) | |||
piBoardRevOops ("Bogus revision line (too small)") ; | |||
// If you have overvolted the Pi, then it appears that the revision | |||
// has 100000 added to it! | |||
// The actual condition for it being set is: | |||
// (force_turbo || current_limit_override || temp_limit>85) && over_voltage>0 | |||
// This test is not correct for the new encoding scheme, so we'll remove it here as | |||
// we don't really need it at this point. | |||
/******************** | |||
if (wiringPiDebug) | |||
if (strlen (c) != 4) | |||
printf ("piboardRev: This Pi has/is (force_turbo || current_limit_override || temp_limit>85) && over_voltage>0\n") ; | |||
*******************/ | |||
piGpioLayoutOops ("Bogus revision line (too small)") ; | |||
// Isolate last 4 characters: | |||
// Isolate last 4 characters: (in-case of overvolting or new encoding scheme) | |||
c = c + strlen (c) - 4 ; | |||
if (wiringPiDebug) | |||
printf ("piboardRev: last4Chars are: \"%s\"\n", c) ; | |||
printf ("piGpioLayout: last4Chars are: \"%s\"\n", c) ; | |||
if ( (strcmp (c, "0002") == 0) || (strcmp (c, "0003") == 0)) | |||
boardRev = 1 ; | |||
gpioLayout = 1 ; | |||
else | |||
boardRev = 2 ; // Covers everything else from the B revision 2 to the B+, the Pi v2 and CM's. | |||
gpioLayout = 2 ; // Covers everything else from the B revision 2 to the B+, the Pi v2, v3, zero and CM's. | |||
if (wiringPiDebug) | |||
printf ("piBoardRev: Returning revision: %d\n", boardRev) ; | |||
printf ("piGpioLayoutOops: Returning revision: %d\n", gpioLayout) ; | |||
return boardRev ; | |||
return gpioLayout ; | |||
} | |||
/*** | |||
if (strstr (line, "BCM2709") != NULL) // Pi v2 - no point doing anything more at this point | |||
{ | |||
piModel2 = TRUE ; | |||
fclose (cpuFd) ; | |||
return gpioLayout = 2 ; | |||
} | |||
else if (strstr (line, "BCM2708") == NULL) | |||
{ | |||
} | |||
***/ | |||
// Now do the rest of it as before - we just need to see if it's an older | |||
// Rev 1 as anything else is rev 2. | |||
/* | |||
* piBoardId: | |||
@@ -822,20 +838,32 @@ int piBoardRev (void) | |||
* 0003 - Model B, Rev 1.1, 256MB, Egoman, Fuses/D14 removed. | |||
* | |||
* Newer Pi's with remapped GPIO: | |||
* 0004 - Model B, Rev 2, 256MB, Sony | |||
* 0005 - Model B, Rev 2, 256MB, Qisda | |||
* 0006 - Model B, Rev 2, 256MB, Egoman | |||
* 0007 - Model A, Rev 2, 256MB, Egoman | |||
* 0008 - Model A, Rev 2, 256MB, Sony | |||
* 0009 - Model A, Rev 2, 256MB, Qisda | |||
* 000d - Model B, Rev 2, 512MB, Egoman (Red Pi, Blue Pi?) | |||
* 000e - Model B, Rev 2, 512MB, Sony | |||
* 000f - Model B, Rev 2, 512MB, Qisda | |||
* 0004 - Model B, Rev 1.2, 256MB, Sony | |||
* 0005 - Model B, Rev 1.2, 256MB, Egoman | |||
* 0006 - Model B, Rev 1.2, 256MB, Egoman | |||
* | |||
* 0007 - Model A, Rev 1.2, 256MB, Egoman | |||
* 0008 - Model A, Rev 1.2, 256MB, Sony | |||
* 0009 - Model A, Rev 1.2, 256MB, Egoman | |||
* | |||
* 000d - Model B, Rev 1.2, 512MB, Egoman (Red Pi, Blue Pi?) | |||
* 000e - Model B, Rev 1.2, 512MB, Sony | |||
* 000f - Model B, Rev 1.2, 512MB, Egoman | |||
* | |||
* 0010 - Model B+, Rev 1.2, 512MB, Sony | |||
* 0011 - Pi CM, Rev 1.2, 512MB, Sony | |||
* 0012 - Model A+ Rev 1.2, 256MB, Sony | |||
* 0014 - Pi CM, Rev 1.1, 512MB, Sony (Actual Revision might be different) | |||
* 0015 - Model A+ Rev 1.1, 256MB, Sony | |||
* 0013 - Model B+ Rev 1.2, 512MB, Embest | |||
* 0016 - Model B+ Rev 1.2, 512MB, Sony | |||
* 0019 - Model B+ Rev 1.2, 512MB, Egoman | |||
* | |||
* 0011 - Pi CM, Rev 1.1, 512MB, Sony | |||
* 0014 - Pi CM, Rev 1.1, 512MB, Embest | |||
* 0017 - Pi CM, Rev 1.1, 512MB, Sony | |||
* 001a - Pi CM, Rev 1.1, 512MB, Egoman | |||
* | |||
* 0012 - Model A+ Rev 1.1, 256MB, Sony | |||
* 0015 - Model A+ Rev 1.1, 512MB, Embest | |||
* 0018 - Model A+ Rev 1.1, 256MB, Sony | |||
* 001b - Model A+ Rev 1.1, 256MB, Egoman | |||
* | |||
* A small thorn is the olde style overvolting - that will add in | |||
* 1000000 | |||
@@ -870,10 +898,10 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
// Will deal with the properly later on - for now, lets just get it going... | |||
// unsigned int modelNum ; | |||
(void)piBoardRev () ; // Call this first to make sure all's OK. Don't care about the result. | |||
(void)piGpioLayout () ; // Call this first to make sure all's OK. Don't care about the result. | |||
if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL) | |||
piBoardRevOops ("Unable to open /proc/cpuinfo") ; | |||
piGpioLayoutOops ("Unable to open /proc/cpuinfo") ; | |||
while (fgets (line, 120, cpuFd) != NULL) | |||
if (strncmp (line, "Revision", 8) == 0) | |||
@@ -882,7 +910,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
fclose (cpuFd) ; | |||
if (strncmp (line, "Revision", 8) != 0) | |||
piBoardRevOops ("No \"Revision\" line") ; | |||
piGpioLayoutOops ("No \"Revision\" line") ; | |||
// Chomp trailing CR/NL | |||
@@ -901,7 +929,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
break ; | |||
if (*c != ':') | |||
piBoardRevOops ("Bogus \"Revision\" line (no colon)") ; | |||
piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ; | |||
// Chomp spaces | |||
@@ -910,7 +938,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
++c ; | |||
if (!isxdigit (*c)) | |||
piBoardRevOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ; | |||
piGpioLayoutOops ("Bogus \"Revision\" line (no hex digit at start of revision)") ; | |||
revision = (unsigned int)strtol (c, NULL, 16) ; // Hex number with no leading 0x | |||
@@ -944,12 +972,12 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
printf ("piBoardId: Old Way: revision is: %s\n", c) ; | |||
if (!isdigit (*c)) | |||
piBoardRevOops ("Bogus \"Revision\" line (no digit at start of revision)") ; | |||
piGpioLayoutOops ("Bogus \"Revision\" line (no digit at start of revision)") ; | |||
// Make sure its long enough | |||
if (strlen (c) < 4) | |||
piBoardRevOops ("Bogus \"Revision\" line (not long enough)") ; | |||
piGpioLayoutOops ("Bogus \"Revision\" line (not long enough)") ; | |||
// If longer than 4, we'll assume it's been overvolted | |||
@@ -963,21 +991,34 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||
/**/ if (strcmp (c, "0002") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0003") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0004") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0005") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 0 ; *maker = PI_MAKER_UNKNOWN ; } | |||
else if (strcmp (c, "0006") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0007") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0008") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; ; } | |||
else if (strcmp (c, "0009") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 0 ; *maker = PI_MAKER_UNKNOWN ; } | |||
else if (strcmp (c, "000d") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "000e") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "000f") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0004") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0005") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0006") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0007") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0008") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; ; } | |||
else if (strcmp (c, "0009") == 0) { *model = PI_MODEL_A ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "000d") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "000e") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "000f") == 0) { *model = PI_MODEL_B ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0010") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0011") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0012") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_2 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0013") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0014") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0015") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0013") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EMBEST ; } | |||
else if (strcmp (c, "0016") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0019") == 0) { *model = PI_MODEL_BP ; *rev = PI_VERSION_1_2 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0011") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0014") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EMBEST ; } | |||
else if (strcmp (c, "0017") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "001a") == 0) { *model = PI_MODEL_CM ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EGOMAN ; } | |||
else if (strcmp (c, "0012") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "0015") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 1 ; *maker = PI_MAKER_EMBEST ; } | |||
else if (strcmp (c, "0018") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_SONY ; } | |||
else if (strcmp (c, "001b") == 0) { *model = PI_MODEL_AP ; *rev = PI_VERSION_1_1 ; *mem = 0 ; *maker = PI_MAKER_EGOMAN ; } | |||
else { *model = 0 ; *rev = 0 ; *mem = 0 ; *maker = 0 ; } | |||
} | |||
} | |||
@@ -1022,9 +1063,6 @@ void setPadDrive (int group, int value) | |||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
if ((group < 0) || (group > 2)) | |||
return ; | |||
@@ -1098,9 +1136,6 @@ void pwmSetRange (unsigned int range) | |||
{ | |||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
*(pwm + PWM0_RANGE) = range ; delayMicroseconds (10) ; | |||
*(pwm + PWM1_RANGE) = range ; delayMicroseconds (10) ; | |||
} | |||
@@ -1122,9 +1157,6 @@ void pwmSetClock (int divisor) | |||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
if (wiringPiDebug) | |||
printf ("Setting to: %d. Current: 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ; | |||
@@ -1177,9 +1209,6 @@ void gpioClockSet (int pin, int freq) | |||
else if (wiringPiMode != WPI_MODE_GPIO) | |||
return ; | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
divi = 19200000 / freq ; | |||
divr = 19200000 % freq ; | |||
divf = (int)((double)divr * 4096.0 / 19200000.0) ; | |||
@@ -1222,13 +1251,13 @@ struct wiringPiNodeStruct *wiringPiFindNode (int pin) | |||
********************************************************************************* | |||
*/ | |||
static void pinModeDummy (struct wiringPiNodeStruct *node, int pin, int mode) { return ; } | |||
static void pullUpDnControlDummy (struct wiringPiNodeStruct *node, int pin, int pud) { return ; } | |||
static int digitalReadDummy (struct wiringPiNodeStruct *node, int pin) { return LOW ; } | |||
static void digitalWriteDummy (struct wiringPiNodeStruct *node, int pin, int value) { return ; } | |||
static void pwmWriteDummy (struct wiringPiNodeStruct *node, int pin, int value) { return ; } | |||
static int analogReadDummy (struct wiringPiNodeStruct *node, int pin) { return 0 ; } | |||
static void analogWriteDummy (struct wiringPiNodeStruct *node, int pin, int value) { return ; } | |||
static void pinModeDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int mode) { return ; } | |||
static void pullUpDnControlDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int pud) { return ; } | |||
static int digitalReadDummy (UNU struct wiringPiNodeStruct *node, UNU int UNU pin) { return LOW ; } | |||
static void digitalWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } | |||
static void pwmWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } | |||
static int analogReadDummy (UNU struct wiringPiNodeStruct *node, UNU int pin) { return 0 ; } | |||
static void analogWriteDummy (UNU struct wiringPiNodeStruct *node, UNU int pin, UNU int value) { return ; } | |||
struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) | |||
{ | |||
@@ -1352,17 +1381,11 @@ void pinMode (int pin, int mode) | |||
softToneCreate (origPin) ; | |||
else if (mode == PWM_TONE_OUTPUT) | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
pinMode (origPin, PWM_OUTPUT) ; // Call myself to enable PWM mode | |||
pwmSetMode (PWM_MODE_MS) ; | |||
} | |||
else if (mode == PWM_OUTPUT) | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin | |||
return ; | |||
@@ -1377,9 +1400,6 @@ void pinMode (int pin, int mode) | |||
} | |||
else if (mode == GPIO_CLOCK) | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
if ((alt = gpioToGpClkALT0 [pin]) == 0) // Not a GPIO_CLOCK pin | |||
return ; | |||
@@ -1534,9 +1554,6 @@ void pwmWrite (int pin, int value) | |||
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin | |||
{ | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
/**/ if (wiringPiMode == WPI_MODE_PINS) | |||
pin = pinToGpio [pin] ; | |||
else if (wiringPiMode == WPI_MODE_PHYS) | |||
@@ -1603,9 +1620,6 @@ void pwmToneWrite (int pin, int freq) | |||
{ | |||
int range ; | |||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||
return ; | |||
if (freq == 0) | |||
pwmWrite (pin, 0) ; // Off | |||
else | |||
@@ -1630,7 +1644,7 @@ void pwmToneWrite (int pin, int freq) | |||
* Reading is just bit fiddling. | |||
* These are wiringPi pin numbers 0..7, or BCM_GPIO pin numbers | |||
* 17, 18, 22, 23, 24, 24, 4 on a Pi v1 rev 0-3 | |||
* 17, 18, 27, 23, 24, 24, 4 on a Pi v1 rev 3 onwards or B+, 2, zero | |||
* 17, 18, 27, 23, 24, 24, 4 on a Pi v1 rev 3 onwards or B+, 2, 3, zero | |||
********************************************************************************* | |||
*/ | |||
@@ -1720,8 +1734,8 @@ void digitalWriteByte2 (const int value) | |||
} | |||
else | |||
{ | |||
*(gpio + gpioToGPCLR [0]) = 0x0FF00000 ; | |||
*(gpio + gpioToGPSET [0]) = (value & 0xFF) << 20 ; | |||
*(gpio + gpioToGPCLR [0]) = (~value & 0xFF) << 20 ; // 0x0FF00000; ILJ > CHANGE: Old causes glitch | |||
*(gpio + gpioToGPSET [0]) = ( value & 0xFF) << 20 ; | |||
} | |||
} | |||
@@ -1772,18 +1786,20 @@ int waitForInterrupt (int pin, int mS) | |||
// Setup poll structure | |||
polls.fd = fd ; | |||
polls.events = POLLPRI ; // Urgent data! | |||
polls.events = POLLPRI | POLLERR ; | |||
// Wait for it ... | |||
x = poll (&polls, 1, mS) ; | |||
// Do a dummy read to clear the interrupt | |||
// If no error, do a dummy read to clear the interrupt | |||
// A one character read appars to be enough. | |||
// Followed by a seek to reset it. | |||
(void)read (fd, &c, 1) ; | |||
lseek (fd, 0, SEEK_SET) ; | |||
if (x > 0) | |||
{ | |||
lseek (fd, 0, SEEK_SET) ; // Rewind | |||
(void)read (fd, &c, 1) ; // Read & clear | |||
} | |||
return x ; | |||
} | |||
@@ -1797,7 +1813,7 @@ int waitForInterrupt (int pin, int mS) | |||
********************************************************************************* | |||
*/ | |||
static void *interruptHandler (void *arg) | |||
static void *interruptHandler (UNU void *arg) | |||
{ | |||
int myPin ; | |||
@@ -2047,18 +2063,17 @@ unsigned int micros (void) | |||
int wiringPiSetup (void) | |||
{ | |||
int fd ; | |||
int boardRev ; | |||
int model, rev, mem, maker, overVolted ; | |||
static int alreadyCalled = FALSE ; | |||
static int alreadyDoneThis = FALSE ; | |||
// This is here to trap the unwary - those who's program appears to work then fails some | |||
// time later with a weird error message because you run out of file-handles. | |||
// It's actually a fatal error to call any of the wiringPiSetup routines more than once, | |||
// (you run out of file handles!) but I'm fed-up with the useless twats who email | |||
// me bleating that there is a bug in my code, so screw-em. | |||
if (alreadyCalled) | |||
(void)wiringPiFailure (WPI_FATAL, "wiringPiSetup*: You must only call this once per program run. This is a fatal error. Please fix your code.\n") ; | |||
alreadyCalled = TRUE ; | |||
if (alreadyDoneThis) | |||
return 0 ; | |||
alreadyDoneThis = TRUE ; | |||
if (getenv (ENV_DEBUG) != NULL) | |||
wiringPiDebug = TRUE ; | |||
@@ -2066,101 +2081,99 @@ int wiringPiSetup (void) | |||
if (getenv (ENV_CODES) != NULL) | |||
wiringPiReturnCodes = TRUE ; | |||
if (getenv (ENV_GPIOMEM) != NULL) | |||
wiringPiTryGpioMem = TRUE ; | |||
if (wiringPiDebug) | |||
{ | |||
printf ("wiringPi: wiringPiSetup called\n") ; | |||
if (wiringPiTryGpioMem) | |||
printf ("wiringPi: Using /dev/gpiomem\n") ; | |||
} | |||
boardRev = piBoardRev () ; | |||
// Get the board ID information. We're not really using the information here, | |||
// but it will give us information like the GPIO layout scheme (2 variants | |||
// on the older 26-pin Pi's) and the GPIO peripheral base address. | |||
// and if we're running on a compute module, then wiringPi pin numbers | |||
// don't really many anything, so force native BCM mode anyway. | |||
piBoardId (&model, &rev, &mem, &maker, &overVolted) ; | |||
if (model == PI_MODEL_CM) | |||
wiringPiMode = WPI_MODE_GPIO ; | |||
else | |||
wiringPiMode = WPI_MODE_PINS ; | |||
/**/ if (boardRev == 1) // A, B, Rev 1, 1.1 | |||
/**/ if (piGpioLayout () == 1) // A, B, Rev 1, 1.1 | |||
{ | |||
pinToGpio = pinToGpioR1 ; | |||
physToGpio = physToGpioR1 ; | |||
} | |||
else // A, B, Rev 2, B+, CM, Pi2, Zero | |||
else // A2, B2, A+, B+, CM, Pi2, Pi3, Zero | |||
{ | |||
pinToGpio = pinToGpioR2 ; | |||
physToGpio = physToGpioR2 ; | |||
} | |||
// Note that a Zero is a model 1 | |||
// ... | |||
if (piModel2) | |||
RASPBERRY_PI_PERI_BASE = 0x3F000000 ; | |||
else | |||
RASPBERRY_PI_PERI_BASE = 0x20000000 ; | |||
// Open the master /dev/ memory control device | |||
// See if /dev/gpiomem exists and we can open it... | |||
if (wiringPiTryGpioMem) | |||
switch (model) | |||
{ | |||
if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/gpiomem: %s\n", strerror (errno)) ; | |||
RASPBERRY_PI_PERI_BASE = 0 ; | |||
case PI_MODEL_A: case PI_MODEL_B: | |||
case PI_MODEL_AP: case PI_MODEL_BP: | |||
case PI_ALPHA: case PI_MODEL_CM: case PI_MODEL_ZERO: | |||
piGpioBase = GPIO_PERI_BASE_OLD ; | |||
break ; | |||
default: | |||
piGpioBase = GPIO_PERI_BASE_NEW ; | |||
break ; | |||
} | |||
// ... otherwise fall back to the original /dev/mem which requires root level access | |||
// Open the master /dev/ memory control device | |||
// Device strategy: December 2016: | |||
// Try /dev/mem. If that fails, then | |||
// try /dev/gpiomem. If that fails then game over. | |||
else | |||
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) | |||
{ | |||
// This check is here because people are too stupid to check for themselves or read | |||
// error messages. | |||
if (geteuid () != 0) | |||
(void)wiringPiFailure (WPI_FATAL, "wiringPiSetup: Must be root. (Did you forget sudo?)\n") ; | |||
if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ; | |||
if ((fd = open ("/dev/gpiomem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem or /dev/gpiomem: %s.\n Try running with sudo?\n", strerror (errno)) ; | |||
piGpioBase = 0 ; | |||
} | |||
// Set the offsets into the memory interface. | |||
GPIO_PADS = RASPBERRY_PI_PERI_BASE + 0x00100000 ; | |||
GPIO_CLOCK_BASE = RASPBERRY_PI_PERI_BASE + 0x00101000 ; | |||
GPIO_BASE = RASPBERRY_PI_PERI_BASE + 0x00200000 ; | |||
GPIO_TIMER = RASPBERRY_PI_PERI_BASE + 0x0000B000 ; | |||
GPIO_PWM = RASPBERRY_PI_PERI_BASE + 0x0020C000 ; | |||
GPIO_PADS = piGpioBase + 0x00100000 ; | |||
GPIO_CLOCK_BASE = piGpioBase + 0x00101000 ; | |||
GPIO_BASE = piGpioBase + 0x00200000 ; | |||
GPIO_TIMER = piGpioBase + 0x0000B000 ; | |||
GPIO_PWM = piGpioBase + 0x0020C000 ; | |||
// Map the individual hardware components | |||
// GPIO: | |||
gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ; | |||
if ((int32_t)gpio == -1) | |||
if (gpio == MAP_FAILED) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ; | |||
// PWM | |||
pwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PWM) ; | |||
if ((int32_t)pwm == -1) | |||
if (pwm == MAP_FAILED) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PWM) failed: %s\n", strerror (errno)) ; | |||
// Clock control (needed for PWM) | |||
clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_BASE) ; | |||
if ((int32_t)clk == -1) | |||
if (clk == MAP_FAILED) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ; | |||
// The drive pads | |||
pads = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_PADS) ; | |||
if ((int32_t)pads == -1) | |||
if (pads == MAP_FAILED) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PADS) failed: %s\n", strerror (errno)) ; | |||
#ifdef USE_TIMER | |||
// The system timer | |||
timer = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_TIMER) ; | |||
if ((int32_t)timer == -1) | |||
if (timer == MAP_FAILED) | |||
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (TIMER) failed: %s\n", strerror (errno)) ; | |||
// Set the timer to free-running, 1MHz. | |||
@@ -2174,14 +2187,6 @@ int wiringPiSetup (void) | |||
initialiseEpoch () ; | |||
// If we're running on a compute module, then wiringPi pin numbers don't really many anything... | |||
piBoardId (&model, &rev, &mem, &maker, &overVolted) ; | |||
if (model == PI_MODEL_CM) | |||
wiringPiMode = WPI_MODE_GPIO ; | |||
else | |||
wiringPiMode = WPI_MODE_PINS ; | |||
return 0 ; | |||
} | |||
@@ -2241,18 +2246,19 @@ int wiringPiSetupPhys (void) | |||
int wiringPiSetupSys (void) | |||
{ | |||
int boardRev ; | |||
int pin ; | |||
char fName [128] ; | |||
static int alreadyCalled = FALSE ; | |||
// This is here to trap the unwary - those who's program appears to work then fails some | |||
// time later with a weird error message because you run out of file-handles. | |||
static int alreadyDoneThis = FALSE ; | |||
if (alreadyCalled) | |||
(void)wiringPiFailure (WPI_FATAL, "wiringPiSetupSys: You must only call this once per program run. This is a fatal error. Please fix your code.\n") ; | |||
// It's actually a fatal error to call any of the wiringPiSetup routines more than once, | |||
// (you run out of file handles!) but I'm fed-up with the useless twats who email | |||
// me bleating that there is a bug in my code, so screw-em. | |||
alreadyCalled = TRUE ; | |||
if (alreadyDoneThis) | |||
return 0 ; | |||
alreadyDoneThis = TRUE ; | |||
if (getenv (ENV_DEBUG) != NULL) | |||
wiringPiDebug = TRUE ; | |||
@@ -2263,9 +2269,7 @@ int wiringPiSetupSys (void) | |||
if (wiringPiDebug) | |||
printf ("wiringPi: wiringPiSetupSys called\n") ; | |||
boardRev = piBoardRev () ; | |||
if (boardRev == 1) | |||
if (piGpioLayout () == 1) | |||
{ | |||
pinToGpio = pinToGpioR1 ; | |||
physToGpio = physToGpioR1 ; | |||
@@ -95,7 +95,7 @@ | |||
#define PI_MAKER_SONY 0 | |||
#define PI_MAKER_EGOMAN 1 | |||
#define PI_MAKER_MBEST 2 | |||
#define PI_MAKER_EMBEST 2 | |||
#define PI_MAKER_UNKNOWN 3 | |||
extern const char *piModelNames [16] ; | |||
@@ -190,7 +190,7 @@ extern int wiringPiSetupPiFaceForGpioProg (void) ; // Don't use this - for gpio | |||
// On-Board Raspberry Pi hardware specific stuff | |||
extern int piBoardRev (void) ; | |||
extern int piGpioLayout (void) ; | |||
extern void piBoardId (int *model, int *rev, int *mem, int *maker, int *overVolted) ; | |||
extern int wpiPinToGpio (int wpiPin) ; | |||
extern int physPinToGpio (int physPin) ; | |||
@@ -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,35 @@ int serialOpen (const char *device, const int baud) | |||
switch (baud) | |||
{ | |||
case 50: myBaud = B50 ; break ; | |||
case 75: myBaud = B75 ; break ; | |||
case 110: myBaud = B110 ; break ; | |||
case 134: myBaud = B134 ; break ; | |||
case 150: myBaud = B150 ; break ; | |||
case 200: myBaud = B200 ; break ; | |||
case 300: myBaud = B300 ; break ; | |||
case 600: myBaud = B600 ; break ; | |||
case 1200: myBaud = B1200 ; break ; | |||
case 1800: myBaud = B1800 ; break ; | |||
case 2400: myBaud = B2400 ; break ; | |||
case 4800: myBaud = B4800 ; break ; | |||
case 9600: myBaud = B9600 ; break ; | |||
case 19200: myBaud = B19200 ; break ; | |||
case 38400: myBaud = B38400 ; break ; | |||
case 57600: myBaud = B57600 ; break ; | |||
case 115200: myBaud = B115200 ; break ; | |||
case 230400: myBaud = B230400 ; break ; | |||
case 50: myBaud = B50 ; break ; | |||
case 75: myBaud = B75 ; break ; | |||
case 110: myBaud = B110 ; break ; | |||
case 134: myBaud = B134 ; break ; | |||
case 150: myBaud = B150 ; break ; | |||
case 200: myBaud = B200 ; break ; | |||
case 300: myBaud = B300 ; break ; | |||
case 600: myBaud = B600 ; break ; | |||
case 1200: myBaud = B1200 ; break ; | |||
case 1800: myBaud = B1800 ; break ; | |||
case 2400: myBaud = B2400 ; break ; | |||
case 9600: myBaud = B9600 ; break ; | |||
case 19200: myBaud = B19200 ; break ; | |||
case 38400: myBaud = B38400 ; break ; | |||
case 57600: myBaud = B57600 ; break ; | |||
case 115200: myBaud = B115200 ; break ; | |||
case 230400: myBaud = B230400 ; break ; | |||
case 460800: myBaud = B460800 ; break ; | |||
case 500000: myBaud = B500000 ; break ; | |||
case 576000: myBaud = B576000 ; break ; | |||
case 921600: myBaud = B921600 ; break ; | |||
case 1000000: myBaud = B1000000 ; break ; | |||
case 1152000: myBaud = B1152000 ; break ; | |||
case 1500000: myBaud = B1500000 ; break ; | |||
case 2000000: myBaud = B2000000 ; break ; | |||
case 2500000: myBaud = B2500000 ; break ; | |||
case 3000000: myBaud = B3000000 ; break ; | |||
case 3500000: myBaud = B3500000 ; break ; | |||
case 4000000: myBaud = B4000000 ; break ; | |||
default: | |||
return -2 ; | |||
@@ -96,7 +107,7 @@ int serialOpen (const char *device, const int baud) | |||
options.c_cc [VMIN] = 0 ; | |||
options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds) | |||
tcsetattr (fd, TCSANOW | TCSAFLUSH, &options) ; | |||
tcsetattr (fd, TCSANOW, &options) ; | |||
ioctl (fd, TIOCMGET, &status); | |||
@@ -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,70 @@ static int doExtensionPcf8591 (char *progName, int pinBase, char *params) | |||
/* | |||
* doExtensionPseudoPins: | |||
* 64 Memory resident pseudo pins | |||
* pseudoPins:base | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionPseudoPins (char *progName, int pinBase, char *params) | |||
{ | |||
pseudoPinsSetup (pinBase) ; | |||
printf ("pseudoPins: %d\n", pinBase) ; | |||
return TRUE ; | |||
} | |||
/* | |||
* doExtensionBmp180: | |||
* Analog Temp + Pressure | |||
* bmp180:base | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionBmp180 (char *progName, int pinBase, char *params) | |||
{ | |||
bmp180Setup (pinBase) ; | |||
return TRUE ; | |||
} | |||
/* | |||
* doExtensionHtu21d: | |||
* Analog humidity + Pressure | |||
* htu21d:base | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionHtu21d (char *progName, int pinBase, char *params) | |||
{ | |||
htu21dSetup (pinBase) ; | |||
return TRUE ; | |||
} | |||
/* | |||
* doExtensionDs18b20: | |||
* 1-Wire Temperature | |||
* htu21d:base:serialNum | |||
********************************************************************************* | |||
*/ | |||
static int doExtensionDs18b20 (char *progName, int pinBase, char *params) | |||
{ | |||
char *serialNum ; | |||
if ((params = extractStr (progName, params, &serialNum)) == NULL) | |||
return FALSE ; | |||
return ds18b20Setup (pinBase, serialNum) ; | |||
} | |||
/* | |||
* doExtensionMax31855: | |||
* Analog IO | |||
* max31855:base:spiChan | |||
@@ -677,6 +745,10 @@ static struct extensionFunctionStruct extensionFunctions [] = | |||
{ "sr595", &doExtensionSr595 }, | |||
{ "pcf8574", &doExtensionPcf8574 }, | |||
{ "pcf8591", &doExtensionPcf8591 }, | |||
{ "bmp180", &doExtensionBmp180 }, | |||
{ "pseudoPins", &doExtensionPseudoPins }, | |||
{ "htu21d", &doExtensionHtu21d }, | |||
{ "ds18b20", &doExtensionDs18b20 }, | |||
{ "mcp3002", &doExtensionMcp3002 }, | |||
{ "mcp3004", &doExtensionMcp3004 }, | |||
{ "mcp4802", &doExtensionMcp4802 }, | |||