@@ -1 +1 @@ | |||||
2.32 | |||||
2.39 |
@@ -6,7 +6,7 @@ | |||||
# Copyright (c) 2012-2015 Gordon Henderson | # Copyright (c) 2012-2015 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # it under the terms of the GNU Lesser General Public License as published by | ||||
@@ -1,5 +1,5 @@ | |||||
Package: wiringpi | Package: wiringpi | ||||
Version: 2.32 | |||||
Version: 2.38 | |||||
Section: libraries | Section: libraries | ||||
Priority: optional | Priority: optional | ||||
Architecture: armhf | Architecture: armhf | ||||
@@ -7,4 +7,4 @@ Depends: libc6 | |||||
Maintainer: Gordon Henderson <projects@drogon.net> | Maintainer: Gordon Henderson <projects@drogon.net> | ||||
Description: The wiringPi libraries, headers and gpio command | Description: The wiringPi libraries, headers and gpio command | ||||
Libraries to allow GPIO access on a Raspberry Pi from C and C++ | 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: | # 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: | # This file is part of wiringPi: | ||||
# https://projects.drogon.net/raspberry-pi/wiringpi/ | # https://projects.drogon.net/raspberry-pi/wiringpi/ | ||||
@@ -101,7 +101,7 @@ int gertboardAnalogRead (const int chan) | |||||
wiringPiSPIDataRW (SPI_A2D, spiData, 2) ; | 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.: | * 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 | * This file to interface with the PiFace peripheral device which | ||||
* has an MCP23S17 GPIO device connected via the SPI bus. | * has an MCP23S17 GPIO device connected via the SPI bus. | ||||
@@ -1,6 +1,6 @@ | |||||
# | # | ||||
# Makefile: | # Makefile: | ||||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||||
# wiringPi - A "wiring" library for the Raspberry Pi | |||||
# https://projects.drogon.net/wiring-pi | # https://projects.drogon.net/wiring-pi | ||||
# | # | ||||
# Copyright (c) 2012-2015 Gordon Henderson | # Copyright (c) 2012-2015 Gordon Henderson | ||||
@@ -1,12 +1,12 @@ | |||||
# | # | ||||
# Makefile: | # Makefile: | ||||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||||
# wiringPi - A "wiring" library for the Raspberry Pi | |||||
# https://projects.drogon.net/wiring-pi | # https://projects.drogon.net/wiring-pi | ||||
# | # | ||||
# Copyright (c) 2012 Gordon Henderson | # Copyright (c) 2012 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # it under the terms of the GNU Lesser General Public License as published by | ||||
@@ -1,12 +1,12 @@ | |||||
# | # | ||||
# Makefile: | # Makefile: | ||||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||||
# wiringPi - A "wiring" library for the Raspberry Pi | |||||
# https://projects.drogon.net/wiring-pi | # https://projects.drogon.net/wiring-pi | ||||
# | # | ||||
# Copyright (c) 2012-2015 Gordon Henderson | # Copyright (c) 2012-2015 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # it under the terms of the GNU Lesser General Public License as published by | ||||
@@ -1,12 +1,12 @@ | |||||
# | # | ||||
# Makefile: | # Makefile: | ||||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||||
# wiringPi - A "wiring" library for the Raspberry Pi | |||||
# https://projects.drogon.net/wiring-pi | # https://projects.drogon.net/wiring-pi | ||||
# | # | ||||
# Copyright (c) 2012-2013 Gordon Henderson | # Copyright (c) 2012-2013 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # it under the terms of the GNU Lesser General Public License as published by | ||||
@@ -1,12 +1,12 @@ | |||||
# | # | ||||
# Makefile: | # Makefile: | ||||
# wiringPi - Wiring Compatable library for the Raspberry Pi | |||||
# wiringPi - A "wiring" library for the Raspberry Pi | |||||
# https://projects.drogon.net/wiring-pi | # https://projects.drogon.net/wiring-pi | ||||
# | # | ||||
# Copyright (c) 2012-2015 Gordon Henderson | # Copyright (c) 2012-2015 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # 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. | # A swiss-army knige of GPIO shenanigans. | ||||
# https://projects.drogon.net/wiring-pi | # https://projects.drogon.net/wiring-pi | ||||
# | # | ||||
# Copyright (c) 2012-2015 Gordon Henderson | |||||
# Copyright (c) 2012-2016 Gordon Henderson | |||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # it under the terms of the GNU Lesser General Public License as published by | ||||
@@ -34,10 +34,10 @@ endif | |||||
DEBUG = -O2 | DEBUG = -O2 | ||||
CC = gcc | CC = gcc | ||||
INCLUDE = -I$(DESTDIR)$(PREFIX)/include | INCLUDE = -I$(DESTDIR)$(PREFIX)/include | ||||
CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe | |||||
CFLAGS = $(DEBUG) -Wall -Wextra $(INCLUDE) -Winline -pipe | |||||
LDFLAGS = -L$(DESTDIR)$(PREFIX)/lib | LDFLAGS = -L$(DESTDIR)$(PREFIX)/lib | ||||
LIBS = -lwiringPi -lwiringPiDev -lpthread | |||||
LIBS = -lwiringPi -lwiringPiDev -lpthread -lrt -lm | |||||
# May not need to alter anything below this line | # May not need to alter anything below this line | ||||
############################################################################### | ############################################################################### | ||||
@@ -85,6 +85,8 @@ install-deb: gpio | |||||
$Q echo "[Install: deb]" | $Q echo "[Install: deb]" | ||||
$Q install -m 0755 -d ~/wiringPi/debian-template/wiringPi/usr/bin | $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 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 | .PHONY: uninstall | ||||
uninstall: | uninstall: | ||||
@@ -98,4 +100,4 @@ depend: | |||||
# DO NOT DELETE | # DO NOT DELETE | ||||
gpio.o: version.h | |||||
gpio.o: ../version.h |
@@ -2,7 +2,7 @@ | |||||
* gpio.c: | * gpio.c: | ||||
* Swiss-Army-Knife, Set-UID command-line interface to the Raspberry | * Swiss-Army-Knife, Set-UID command-line interface to the Raspberry | ||||
* Pi's GPIO. | * Pi's GPIO. | ||||
* Copyright (c) 2012-2015 Gordon Henderson | |||||
* Copyright (c) 2012-2017 Gordon Henderson | |||||
*********************************************************************** | *********************************************************************** | ||||
* This file is part of wiringPi: | * This file is part of wiringPi: | ||||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | * https://projects.drogon.net/raspberry-pi/wiringpi/ | ||||
@@ -40,7 +40,7 @@ | |||||
#include <gertboard.h> | #include <gertboard.h> | ||||
#include <piFace.h> | #include <piFace.h> | ||||
#include "version.h" | |||||
#include "../version.h" | |||||
extern int wiringPiDebug ; | extern int wiringPiDebug ; | ||||
@@ -57,14 +57,19 @@ extern void doPins (void) ; | |||||
#define PI_USB_POWER_CONTROL 38 | #define PI_USB_POWER_CONTROL 38 | ||||
#define I2CDETECT "/usr/sbin/i2cdetect" | #define I2CDETECT "/usr/sbin/i2cdetect" | ||||
#define MODPROBE "/sbin/modprobe" | |||||
#define RMMOD "/sbin/rmmod" | |||||
int wpMode ; | int wpMode ; | ||||
char *usage = "Usage: gpio -v\n" | char *usage = "Usage: gpio -v\n" | ||||
" gpio -h\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 [-p] <read/write/wb> ...\n" | ||||
" gpio <read/write/aread/awritewb/pwm/clock/mode> ...\n" | " gpio <read/write/aread/awritewb/pwm/clock/mode> ...\n" | ||||
" gpio <toggle/blink> <pin>\n" | |||||
" gpio readall/reset\n" | " gpio readall/reset\n" | ||||
" gpio unexportall/exports\n" | " gpio unexportall/exports\n" | ||||
" gpio export/edge/unexport ...\n" | " gpio export/edge/unexport ...\n" | ||||
@@ -76,6 +81,8 @@ char *usage = "Usage: gpio -v\n" | |||||
" gpio load spi/i2c\n" | " gpio load spi/i2c\n" | ||||
" gpio unload spi/i2c\n" | " gpio unload spi/i2c\n" | ||||
" gpio i2cd/i2cdetect\n" | " gpio i2cd/i2cdetect\n" | ||||
" gpio rbx/rbd\n" | |||||
" gpio wb <value>\n" | |||||
" gpio usbp high/low\n" | " gpio usbp high/low\n" | ||||
" gpio gbr <channel>\n" | " gpio gbr <channel>\n" | ||||
" gpio gbw <channel> <value>" ; // No trailing newline needed here. | " 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: | * changeOwner: | ||||
* Change the ownership of the file to the real userId of the calling | * Change the ownership of the file to the real userId of the calling | ||||
* program so we can access it. | * program so we can access it. | ||||
@@ -230,15 +276,18 @@ static void doLoad (int argc, char *argv []) | |||||
else | else | ||||
_doLoadUsage (argv) ; | _doLoadUsage (argv) ; | ||||
if (findExecutable ("modprobe") == NULL) | |||||
printf ("No found\n") ; | |||||
if (!moduleLoaded (module1)) | if (!moduleLoaded (module1)) | ||||
{ | { | ||||
sprintf (cmd, "/sbin/modprobe %s%s", module1, args1) ; | |||||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module1, args1) ; | |||||
system (cmd) ; | system (cmd) ; | ||||
} | } | ||||
if (!moduleLoaded (module2)) | if (!moduleLoaded (module2)) | ||||
{ | { | ||||
sprintf (cmd, "/sbin/modprobe %s%s", module2, args2) ; | |||||
sprintf (cmd, "%s %s%s", findExecutable (MODPROBE), module2, args2) ; | |||||
system (cmd) ; | system (cmd) ; | ||||
} | } | ||||
@@ -292,13 +341,13 @@ static void doUnLoad (int argc, char *argv []) | |||||
if (moduleLoaded (module1)) | if (moduleLoaded (module1)) | ||||
{ | { | ||||
sprintf (cmd, "/sbin/rmmod %s", module1) ; | |||||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module1) ; | |||||
system (cmd) ; | system (cmd) ; | ||||
} | } | ||||
if (moduleLoaded (module2)) | if (moduleLoaded (module2)) | ||||
{ | { | ||||
sprintf (cmd, "/sbin/rmmod %s", module2) ; | |||||
sprintf (cmd, "%s %s", findExecutable (RMMOD), module2) ; | |||||
system (cmd) ; | 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)) ; | fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ; | ||||
return ; | return ; | ||||
@@ -328,7 +376,8 @@ static void doI2Cdetect (int argc, char *argv []) | |||||
return ; | return ; | ||||
} | } | ||||
sprintf (command, "%s -y %d", I2CDETECT, port) ; | |||||
command = malloc (strlen (c) + 16) ; | |||||
sprintf (command, "%s -y %d", c, port) ; | |||||
if (system (command) < 0) | if (system (command) < 0) | ||||
fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ; | 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 fd ; | ||||
int i, l, first ; | 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 ("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") ; | 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: | * 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: | * doRead: | ||||
* Read a pin and return the value | * 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: | * doPwmTone: | ||||
* Output a tone in a PWM pin | * Output a tone in a PWM pin | ||||
********************************************************************************* | ********************************************************************************* | ||||
@@ -1162,9 +1263,14 @@ static void doVersion (char *argv []) | |||||
{ | { | ||||
int model, rev, mem, maker, warranty ; | int model, rev, mem, maker, warranty ; | ||||
struct stat statBuf ; | 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 ("This is free software with ABSOLUTELY NO WARRANTY.\n") ; | ||||
printf ("For details type: %s -warranty\n", argv [0]) ; | printf ("For details type: %s -warranty\n", argv [0]) ; | ||||
printf ("\n") ; | printf ("\n") ; | ||||
@@ -1179,12 +1285,18 @@ static void doVersion (char *argv []) | |||||
if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ... | if (stat ("/proc/device-tree", &statBuf) == 0) // We're on a devtree system ... | ||||
printf (" * Device tree is enabled.\n") ; | 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 | else | ||||
printf (" * Root or sudo required for GPIO access.\n") ; | 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)) | if ((strcmp (argv [1], "-R") == 0) || (strcmp (argv [1], "-V") == 0)) | ||||
{ | { | ||||
printf ("%d\n", piBoardRev ()) ; | |||||
printf ("%d\n", piGpioLayout ()) ; | |||||
return 0 ; | return 0 ; | ||||
} | } | ||||
@@ -1240,7 +1352,7 @@ int main (int argc, char *argv []) | |||||
if (strcasecmp (argv [1], "-warranty") == 0) | if (strcasecmp (argv [1], "-warranty") == 0) | ||||
{ | { | ||||
printf ("gpio version: %s\n", VERSION) ; | 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 ("\n") ; | ||||
printf (" This program is free software; you can redistribute it and/or modify\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") ; | 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 | // 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) | 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 | if (!loadWPiExtension (argv [0], argv [2], TRUE)) // Prints its own error messages | ||||
exit (EXIT_FAILURE) ; | exit (EXIT_FAILURE) ; | ||||
// Shift args down by 2 | |||||
for (i = 3 ; i < argc ; ++i) | for (i = 3 ; i < argc ; ++i) | ||||
argv [i - 2] = argv [i] ; | argv [i - 2] = argv [i] ; | ||||
argc -= 2 ; | argc -= 2 ; | ||||
@@ -1375,6 +1492,7 @@ int main (int argc, char *argv []) | |||||
// GPIO Nicies | // GPIO Nicies | ||||
else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle (argc, argv) ; | else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle (argc, argv) ; | ||||
else if (strcasecmp (argv [1], "blink" ) == 0) doBlink (argc, argv) ; | |||||
// Pi Specifics | // 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], "i2cd" ) == 0) doI2Cdetect (argc, argv) ; | ||||
else if (strcasecmp (argv [1], "reset" ) == 0) doReset (argv [0]) ; | 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], "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], "clock" ) == 0) doClock (argc, argv) ; | ||||
else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ; | else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ; | ||||
else | else | ||||
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* pins.c: | * pins.c: | ||||
* Just display a handy Pi pinnout diagram. | * 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: | * This file is part of wiringPi: | ||||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | * https://projects.drogon.net/raspberry-pi/wiringpi/ | ||||
@@ -5,7 +5,7 @@ | |||||
# Copyright (c) 2013-2015 Gordon Henderson | # Copyright (c) 2013-2015 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # it under the terms of the GNU Lesser General Public License as published by | ||||
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* readall.c: | * readall.c: | ||||
* The readall functions - getting a bit big, so split them out. | * 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: | * This file is part of wiringPi: | ||||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | * https://projects.drogon.net/raspberry-pi/wiringpi/ | ||||
@@ -118,7 +118,7 @@ static char *physNames [64] = | |||||
NULL, | NULL, | ||||
" 3.3v", "5v ", | " 3.3v", "5v ", | ||||
" SDA.1", "5V ", | |||||
" SDA.1", "5v ", | |||||
" SCL.1", "0v ", | " SCL.1", "0v ", | ||||
"GPIO. 7", "TxD ", | "GPIO. 7", "TxD ", | ||||
" 0v", "RxD ", | " 0v", "RxD ", | ||||
@@ -348,7 +348,7 @@ void doReadall (void) | |||||
abReadall (model, rev) ; | 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)) | else if ((model == PI_MODEL_BP) || (model == PI_MODEL_AP) || (model == PI_MODEL_2) || (model == PI_MODEL_3) || (model == PI_MODEL_ZERO)) | ||||
piPlusReadall (model) ; | piPlusReadall (model) ; | ||||
else if (model == PI_MODEL_CM) | |||||
else if ((model == PI_MODEL_CM) || (model == PI_MODEL_CM3)) | |||||
allReadall () ; | allReadall () ; | ||||
else | else | ||||
printf ("Oops - unable to determine board type... model: %d\n", model) ; | printf ("Oops - unable to determine board type... model: %d\n", model) ; | ||||
@@ -5,7 +5,7 @@ | |||||
# in-turn. | # in-turn. | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # 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 | # Copyright (c) 2012-2015 Gordon Henderson | ||||
################################################################################# | ################################################################################# | ||||
# This file is part of wiringPi: | # 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 | # 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 | # it under the terms of the GNU Lesser General Public License as published by | ||||
@@ -25,8 +25,12 @@ | |||||
echo Updating to version: `cat VERSION` | 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 | rm -f debian-template/wiringPi/DEBIAN/control | ||||
cat > debian-template/wiringPi/DEBIAN/control <<EOF | cat > debian-template/wiringPi/DEBIAN/control <<EOF | ||||
@@ -39,5 +43,5 @@ Depends: libc6 | |||||
Maintainer: Gordon Henderson <projects@drogon.net> | Maintainer: Gordon Henderson <projects@drogon.net> | ||||
Description: The wiringPi libraries, headers and gpio command | Description: The wiringPi libraries, headers and gpio command | ||||
Libraries to allow GPIO access on a Raspberry Pi from C and C++ | 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 | 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 | CC = gcc | ||||
INCLUDE = -I. | INCLUDE = -I. | ||||
DEFS = -D_GNU_SOURCE | 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 \ | mcp3002.c mcp3004.c mcp4802.c mcp3422.c \ | ||||
max31855.c max5322.c ads1115.c \ | max31855.c max5322.c ads1115.c \ | ||||
sn3218.c \ | sn3218.c \ | ||||
bmp180.c htu21d.c ds18b20.c \ | |||||
drcSerial.c \ | drcSerial.c \ | ||||
pseudoPins.c \ | |||||
wpiExtensions.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) | OBJ = $(SRC:.c=.o) | ||||
@@ -89,7 +78,7 @@ $(STATIC): $(OBJ) | |||||
$(DYNAMIC): $(OBJ) | $(DYNAMIC): $(OBJ) | ||||
$Q echo "[Link (Dynamic)]" | $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: | .c.o: | ||||
$Q echo [Compile] $< | $Q echo [Compile] $< | ||||
@@ -151,7 +140,7 @@ depend: | |||||
# DO NOT DELETE | # 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 | wiringSerial.o: wiringSerial.h | ||||
wiringShift.o: wiringPi.h wiringShift.h | wiringShift.o: wiringPi.h wiringShift.h | ||||
piHiPri.o: wiringPi.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 | mcp3422.o: wiringPi.h wiringPiI2C.h mcp3422.h | ||||
max31855.o: wiringPi.h wiringPiSPI.h max31855.h | max31855.o: wiringPi.h wiringPiSPI.h max31855.h | ||||
max5322.o: wiringPi.h wiringPiSPI.h max5322.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 | 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 | 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: 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: 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 | if ( (data < 0) || (data > 7) ) // Use default if out of range | ||||
data = 4 ; | 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) ; | 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] ; | unsigned char b [2] ; | ||||
b [0] = 0x40 ; | 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 <stdio.h> | ||||
#include <malloc.h> | |||||
#include <pthread.h> | #include <pthread.h> | ||||
#include "wiringPi.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 ; | int pin, mark, space ; | ||||
struct sched_param param ; | struct sched_param param ; | ||||
@@ -71,6 +72,9 @@ static PI_THREAD (softPwmThread) | |||||
param.sched_priority = sched_get_priority_max (SCHED_RR) ; | param.sched_priority = sched_get_priority_max (SCHED_RR) ; | ||||
pthread_setschedparam (pthread_self (), SCHED_RR, ¶m) ; | pthread_setschedparam (pthread_self (), SCHED_RR, ¶m) ; | ||||
pin = *((int *)arg) ; | |||||
free (arg) ; | |||||
pin = newPin ; | pin = newPin ; | ||||
newPin = -1 ; | newPin = -1 ; | ||||
@@ -123,11 +127,16 @@ int softPwmCreate (int pin, int initialValue, int pwmRange) | |||||
{ | { | ||||
int res ; | int res ; | ||||
pthread_t myThread ; | pthread_t myThread ; | ||||
int *passPin ; | |||||
if (range [pin] != 0) // Already running on this pin | if (range [pin] != 0) // Already running on this pin | ||||
return -1 ; | return -1 ; | ||||
if (range <= 0) | |||||
if (pwmRange <= 0) | |||||
return -1 ; | |||||
passPin = malloc (sizeof (*passPin)) ; | |||||
if (passPin == NULL) | |||||
return -1 ; | return -1 ; | ||||
pinMode (pin, OUTPUT) ; | pinMode (pin, OUTPUT) ; | ||||
@@ -136,8 +145,9 @@ int softPwmCreate (int pin, int initialValue, int pwmRange) | |||||
marks [pin] = initialValue ; | marks [pin] = initialValue ; | ||||
range [pin] = pwmRange ; | range [pin] = pwmRange ; | ||||
*passPin = pin ; | |||||
newPin = pin ; | newPin = pin ; | ||||
res = pthread_create (&myThread, NULL, softPwmThread, NULL) ; | |||||
res = pthread_create (&myThread, NULL, softPwmThread, (void *)passPin) ; | |||||
while (newPin != -1) | while (newPin != -1) | ||||
delay (1) ; | delay (1) ; | ||||
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* wiringPi: | * wiringPi: | ||||
* Arduino look-a-like Wiring library for the Raspberry Pi | * 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> | * Additional code for pwmSetClock by Chris Hall <chris@kchall.plus.com> | ||||
* | * | ||||
* Thanks to code samples from Gert Jan van Loo and the | * Thanks to code samples from Gert Jan van Loo and the | ||||
@@ -75,6 +75,7 @@ | |||||
#include "softTone.h" | #include "softTone.h" | ||||
#include "wiringPi.h" | #include "wiringPi.h" | ||||
#include "../version.h" | |||||
// Environment Variables | // Environment Variables | ||||
@@ -129,9 +130,8 @@ struct wiringPiNodeStruct *wiringPiNodes = NULL ; | |||||
// that I can find )-: | // that I can find )-: | ||||
// | // | ||||
// Updates in September 2015 - all now static variables (and apologies for the caps) | // 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_PADS ; | ||||
static volatile unsigned int GPIO_CLOCK_BASE ; | static volatile unsigned int GPIO_CLOCK_BASE ; | ||||
static volatile unsigned int GPIO_BASE ; | static volatile unsigned int GPIO_BASE ; | ||||
@@ -197,13 +197,18 @@ static volatile uint32_t *timer ; | |||||
static volatile uint32_t *timerIrqRaw ; | static volatile uint32_t *timerIrqRaw ; | ||||
#endif | #endif | ||||
// Data for use with the boardId functions. | // Data for use with the boardId functions. | ||||
// The order of entries here to correspond with the PI_MODEL_X | // The order of entries here to correspond with the PI_MODEL_X | ||||
// and PI_VERSION_X defines in wiringPi.h | // and PI_VERSION_X defines in wiringPi.h | ||||
// Only intended for the gpio command - use at your own risk! | // 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] = | const char *piModelNames [16] = | ||||
{ | { | ||||
@@ -217,7 +222,7 @@ const char *piModelNames [16] = | |||||
"Unknown07", // 07 | "Unknown07", // 07 | ||||
"Pi 3", // 08 | "Pi 3", // 08 | ||||
"Pi Zero", // 09 | "Pi Zero", // 09 | ||||
"Unknown10", // 10 | |||||
"CM3", // 10 | |||||
"Unknown11", // 11 | "Unknown11", // 11 | ||||
"Unknown12", // 12 | "Unknown12", // 12 | ||||
"Unknown13", // 13 | "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. | * Return a number representing the hardware revision of the board. | ||||
* This is not strictly the board revision but is used to check the | * 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 | * 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 | * 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. | * 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, " -> %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) ; | exit (EXIT_FAILURE) ; | ||||
} | } | ||||
int piBoardRev (void) | |||||
int piGpioLayout (void) | |||||
{ | { | ||||
FILE *cpuFd ; | FILE *cpuFd ; | ||||
char line [120] ; | char line [120] ; | ||||
char *c ; | 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) | 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 | // 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 | // on a Pi. I'm getting fed-up with people whinging at me because | ||||
@@ -700,23 +709,23 @@ int piBoardRev (void) | |||||
break ; | break ; | ||||
if (strncmp (line, "Hardware", 8) != 0) | if (strncmp (line, "Hardware", 8) != 0) | ||||
piBoardRevOops ("No hardware line") ; | |||||
piGpioLayoutOops ("No \"Hardware\" line") ; | |||||
if (wiringPiDebug) | 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, "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, "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, "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") ; | fprintf (stderr, "are on your own as wiringPi is designed to support the\n") ; | ||||
@@ -724,8 +733,11 @@ int piBoardRev (void) | |||||
exit (EXIT_FAILURE) ; | 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 | // Isolate the Revision line | ||||
@@ -737,7 +749,7 @@ int piBoardRev (void) | |||||
fclose (cpuFd) ; | fclose (cpuFd) ; | ||||
if (strncmp (line, "Revision", 8) != 0) | if (strncmp (line, "Revision", 8) != 0) | ||||
piBoardRevOops ("No \"Revision\" line") ; | |||||
piGpioLayoutOops ("No \"Revision\" line") ; | |||||
// Chomp trailing CR/NL | // Chomp trailing CR/NL | ||||
@@ -745,7 +757,7 @@ int piBoardRev (void) | |||||
*c = 0 ; | *c = 0 ; | ||||
if (wiringPiDebug) | 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 | // Scan to the first character of the revision number | ||||
@@ -754,7 +766,7 @@ int piBoardRev (void) | |||||
break ; | break ; | ||||
if (*c != ':') | if (*c != ':') | ||||
piBoardRevOops ("Bogus \"Revision\" line (no colon)") ; | |||||
piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ; | |||||
// Chomp spaces | // Chomp spaces | ||||
@@ -763,47 +775,44 @@ int piBoardRev (void) | |||||
++c ; | ++c ; | ||||
if (!isxdigit (*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 | // Make sure its long enough | ||||
if (strlen (c) < 4) | 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 ; | c = c + strlen (c) - 4 ; | ||||
if (wiringPiDebug) | 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)) | if ( (strcmp (c, "0002") == 0) || (strcmp (c, "0003") == 0)) | ||||
boardRev = 1 ; | |||||
gpioLayout = 1 ; | |||||
else | 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) | 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: | * piBoardId: | ||||
* Return the real details of the board we have. | * 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. | * 0003 - Model B, Rev 1.1, 256MB, Egoman, Fuses/D14 removed. | ||||
* | * | ||||
* Newer Pi's with remapped GPIO: | * 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 | * 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 | * A small thorn is the olde style overvolting - that will add in | ||||
* 1000000 | * 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... | // Will deal with the properly later on - for now, lets just get it going... | ||||
// unsigned int modelNum ; | // 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) | 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) | while (fgets (line, 120, cpuFd) != NULL) | ||||
if (strncmp (line, "Revision", 8) == 0) | if (strncmp (line, "Revision", 8) == 0) | ||||
@@ -882,7 +903,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||||
fclose (cpuFd) ; | fclose (cpuFd) ; | ||||
if (strncmp (line, "Revision", 8) != 0) | if (strncmp (line, "Revision", 8) != 0) | ||||
piBoardRevOops ("No \"Revision\" line") ; | |||||
piGpioLayoutOops ("No \"Revision\" line") ; | |||||
// Chomp trailing CR/NL | // Chomp trailing CR/NL | ||||
@@ -901,7 +922,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||||
break ; | break ; | ||||
if (*c != ':') | if (*c != ':') | ||||
piBoardRevOops ("Bogus \"Revision\" line (no colon)") ; | |||||
piGpioLayoutOops ("Bogus \"Revision\" line (no colon)") ; | |||||
// Chomp spaces | // Chomp spaces | ||||
@@ -910,7 +931,7 @@ void piBoardId (int *model, int *rev, int *mem, int *maker, int *warranty) | |||||
++c ; | ++c ; | ||||
if (!isxdigit (*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 | 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 ; | *warranty = bWarranty ; | ||||
if (wiringPiDebug) | 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) ; | bRev, bType, bProc, bMfg, bMem, bWarranty) ; | ||||
} | } | ||||
else // Old way | 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) ; | printf ("piBoardId: Old Way: revision is: %s\n", c) ; | ||||
if (!isdigit (*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 | // Make sure its long enough | ||||
if (strlen (c) < 4) | 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 | // 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 ; } | /**/ 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, "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, "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 ; } | 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 ((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)) | if ((group < 0) || (group > 2)) | ||||
return ; | return ; | ||||
@@ -1098,9 +1129,6 @@ void pwmSetRange (unsigned int range) | |||||
{ | { | ||||
if ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) | 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 + PWM0_RANGE) = range ; delayMicroseconds (10) ; | ||||
*(pwm + PWM1_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 ((wiringPiMode == WPI_MODE_PINS) || (wiringPiMode == WPI_MODE_PHYS) || (wiringPiMode == WPI_MODE_GPIO)) | ||||
{ | { | ||||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||||
return ; | |||||
if (wiringPiDebug) | if (wiringPiDebug) | ||||
printf ("Setting to: %d. Current: 0x%08X\n", divisor, *(clk + PWMCLK_DIV)) ; | 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) | else if (wiringPiMode != WPI_MODE_GPIO) | ||||
return ; | return ; | ||||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||||
return ; | |||||
divi = 19200000 / freq ; | divi = 19200000 / freq ; | ||||
divr = 19200000 % freq ; | divr = 19200000 % freq ; | ||||
divf = (int)((double)divr * 4096.0 / 19200000.0) ; | 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) | struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) | ||||
{ | { | ||||
@@ -1352,17 +1374,11 @@ void pinMode (int pin, int mode) | |||||
softToneCreate (origPin) ; | softToneCreate (origPin) ; | ||||
else if (mode == PWM_TONE_OUTPUT) | 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 | pinMode (origPin, PWM_OUTPUT) ; // Call myself to enable PWM mode | ||||
pwmSetMode (PWM_MODE_MS) ; | pwmSetMode (PWM_MODE_MS) ; | ||||
} | } | ||||
else if (mode == PWM_OUTPUT) | 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 | if ((alt = gpioToPwmALT [pin]) == 0) // Not a hardware capable PWM pin | ||||
return ; | return ; | ||||
@@ -1377,9 +1393,6 @@ void pinMode (int pin, int mode) | |||||
} | } | ||||
else if (mode == GPIO_CLOCK) | 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 | if ((alt = gpioToGpClkALT0 [pin]) == 0) // Not a GPIO_CLOCK pin | ||||
return ; | return ; | ||||
@@ -1534,9 +1547,6 @@ void pwmWrite (int pin, int value) | |||||
if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin | if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin | ||||
{ | { | ||||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||||
return ; | |||||
/**/ if (wiringPiMode == WPI_MODE_PINS) | /**/ if (wiringPiMode == WPI_MODE_PINS) | ||||
pin = pinToGpio [pin] ; | pin = pinToGpio [pin] ; | ||||
else if (wiringPiMode == WPI_MODE_PHYS) | else if (wiringPiMode == WPI_MODE_PHYS) | ||||
@@ -1603,9 +1613,6 @@ void pwmToneWrite (int pin, int freq) | |||||
{ | { | ||||
int range ; | int range ; | ||||
if (RASPBERRY_PI_PERI_BASE == 0) // Ignore for now | |||||
return ; | |||||
if (freq == 0) | if (freq == 0) | ||||
pwmWrite (pin, 0) ; // Off | pwmWrite (pin, 0) ; // Off | ||||
else | else | ||||
@@ -1630,7 +1637,7 @@ void pwmToneWrite (int pin, int freq) | |||||
* Reading is just bit fiddling. | * Reading is just bit fiddling. | ||||
* These are wiringPi pin numbers 0..7, or BCM_GPIO pin numbers | * 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, 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 | 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 | // Setup poll structure | ||||
polls.fd = fd ; | polls.fd = fd ; | ||||
polls.events = POLLPRI ; // Urgent data! | |||||
polls.events = POLLPRI | POLLERR ; | |||||
// Wait for it ... | // Wait for it ... | ||||
x = poll (&polls, 1, mS) ; | 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. | // 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 ; | 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 ; | int myPin ; | ||||
@@ -1922,11 +1931,19 @@ int wiringPiISR (int pin, int mode, void (*function)(void)) | |||||
static void initialiseEpoch (void) | static void initialiseEpoch (void) | ||||
{ | { | ||||
#ifdef OLD_WAY | |||||
struct timeval tv ; | struct timeval tv ; | ||||
gettimeofday (&tv, NULL) ; | gettimeofday (&tv, NULL) ; | ||||
epochMilli = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ; | 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) ; | 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: | * millis: | ||||
* Return a number of milliseconds as an unsigned int. | * Return a number of milliseconds as an unsigned int. | ||||
* Wraps at 49 days. | |||||
********************************************************************************* | ********************************************************************************* | ||||
*/ | */ | ||||
unsigned int millis (void) | unsigned int millis (void) | ||||
{ | { | ||||
struct timeval tv ; | |||||
uint64_t now ; | uint64_t now ; | ||||
#ifdef OLD_WAY | |||||
struct timeval tv ; | |||||
gettimeofday (&tv, NULL) ; | gettimeofday (&tv, NULL) ; | ||||
now = (uint64_t)tv.tv_sec * (uint64_t)1000 + (uint64_t)(tv.tv_usec / 1000) ; | 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) ; | return (uint32_t)(now - epochMilli) ; | ||||
} | } | ||||
@@ -2018,20 +2045,41 @@ unsigned int millis (void) | |||||
/* | /* | ||||
* micros: | * micros: | ||||
* Return a number of microseconds as an unsigned int. | * Return a number of microseconds as an unsigned int. | ||||
* Wraps after 71 minutes. | |||||
********************************************************************************* | ********************************************************************************* | ||||
*/ | */ | ||||
unsigned int micros (void) | unsigned int micros (void) | ||||
{ | { | ||||
struct timeval tv ; | |||||
uint64_t now ; | uint64_t now ; | ||||
#ifdef OLD_WAY | |||||
struct timeval tv ; | |||||
gettimeofday (&tv, NULL) ; | gettimeofday (&tv, NULL) ; | ||||
now = (uint64_t)tv.tv_sec * (uint64_t)1000000 + (uint64_t)tv.tv_usec ; | 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) ; | return (uint32_t)(now - epochMicro) ; | ||||
} | } | ||||
/* | |||||
* wiringPiVersion: | |||||
* Return our current version number | |||||
********************************************************************************* | |||||
*/ | |||||
void wiringPiVersion (int *major, int *minor) | |||||
{ | |||||
*major = VERSION_MAJOR ; | |||||
*minor = VERSION_MINOR ; | |||||
} | |||||
/* | /* | ||||
* wiringPiSetup: | * wiringPiSetup: | ||||
@@ -2047,18 +2095,17 @@ unsigned int micros (void) | |||||
int wiringPiSetup (void) | int wiringPiSetup (void) | ||||
{ | { | ||||
int fd ; | int fd ; | ||||
int boardRev ; | |||||
int model, rev, mem, maker, overVolted ; | 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) | if (getenv (ENV_DEBUG) != NULL) | ||||
wiringPiDebug = TRUE ; | wiringPiDebug = TRUE ; | ||||
@@ -2066,101 +2113,99 @@ int wiringPiSetup (void) | |||||
if (getenv (ENV_CODES) != NULL) | if (getenv (ENV_CODES) != NULL) | ||||
wiringPiReturnCodes = TRUE ; | wiringPiReturnCodes = TRUE ; | ||||
if (getenv (ENV_GPIOMEM) != NULL) | |||||
wiringPiTryGpioMem = TRUE ; | |||||
if (wiringPiDebug) | if (wiringPiDebug) | ||||
{ | |||||
printf ("wiringPi: wiringPiSetup called\n") ; | 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 ; | pinToGpio = pinToGpioR1 ; | ||||
physToGpio = physToGpioR1 ; | physToGpio = physToGpioR1 ; | ||||
} | } | ||||
else // A, B, Rev 2, B+, CM, Pi2, Zero | |||||
else // A2, B2, A+, B+, CM, Pi2, Pi3, Zero | |||||
{ | { | ||||
pinToGpio = pinToGpioR2 ; | pinToGpio = pinToGpioR2 ; | ||||
physToGpio = physToGpioR2 ; | 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. | // 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 | // Map the individual hardware components | ||||
// GPIO: | // GPIO: | ||||
gpio = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_BASE) ; | 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)) ; | return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (GPIO) failed: %s\n", strerror (errno)) ; | ||||
// PWM | // PWM | ||||
pwm = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_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)) ; | return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PWM) failed: %s\n", strerror (errno)) ; | ||||
// Clock control (needed for PWM) | // Clock control (needed for PWM) | ||||
clk = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_CLOCK_BASE) ; | 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)) ; | return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (CLOCK) failed: %s\n", strerror (errno)) ; | ||||
// The drive pads | // The drive pads | ||||
pads = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_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)) ; | return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (PADS) failed: %s\n", strerror (errno)) ; | ||||
#ifdef USE_TIMER | #ifdef USE_TIMER | ||||
// The system timer | // The system timer | ||||
timer = (uint32_t *)mmap(0, BLOCK_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, GPIO_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)) ; | return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: mmap (TIMER) failed: %s\n", strerror (errno)) ; | ||||
// Set the timer to free-running, 1MHz. | // Set the timer to free-running, 1MHz. | ||||
@@ -2174,14 +2219,6 @@ int wiringPiSetup (void) | |||||
initialiseEpoch () ; | 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 ; | return 0 ; | ||||
} | } | ||||
@@ -2241,18 +2278,19 @@ int wiringPiSetupPhys (void) | |||||
int wiringPiSetupSys (void) | int wiringPiSetupSys (void) | ||||
{ | { | ||||
int boardRev ; | |||||
int pin ; | int pin ; | ||||
char fName [128] ; | 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) | if (getenv (ENV_DEBUG) != NULL) | ||||
wiringPiDebug = TRUE ; | wiringPiDebug = TRUE ; | ||||
@@ -2263,9 +2301,7 @@ int wiringPiSetupSys (void) | |||||
if (wiringPiDebug) | if (wiringPiDebug) | ||||
printf ("wiringPi: wiringPiSetupSys called\n") ; | printf ("wiringPi: wiringPiSetupSys called\n") ; | ||||
boardRev = piBoardRev () ; | |||||
if (boardRev == 1) | |||||
if (piGpioLayout () == 1) | |||||
{ | { | ||||
pinToGpio = pinToGpioR1 ; | pinToGpio = pinToGpioR1 ; | ||||
physToGpio = physToGpioR1 ; | physToGpio = physToGpioR1 ; | ||||
@@ -1,7 +1,7 @@ | |||||
/* | /* | ||||
* wiringPi.h: | * wiringPi.h: | ||||
* Arduino like Wiring library for the Raspberry Pi. | * 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: | * This file is part of wiringPi: | ||||
* https://projects.drogon.net/raspberry-pi/wiringpi/ | * https://projects.drogon.net/raspberry-pi/wiringpi/ | ||||
@@ -32,6 +32,10 @@ | |||||
# define FALSE (!TRUE) | # define FALSE (!TRUE) | ||||
#endif | #endif | ||||
// GCC warning suppressor | |||||
#define UNU __attribute__((unused)) | |||||
// Handy defines | // Handy defines | ||||
// wiringPi modes | // wiringPi modes | ||||
@@ -77,16 +81,17 @@ | |||||
// Pi model types and version numbers | // Pi model types and version numbers | ||||
// Intended for the GPIO program Use at your own risk. | // 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 0 | ||||
#define PI_VERSION_1_1 1 | #define PI_VERSION_1_1 1 | ||||
@@ -95,7 +100,7 @@ | |||||
#define PI_MAKER_SONY 0 | #define PI_MAKER_SONY 0 | ||||
#define PI_MAKER_EGOMAN 1 | #define PI_MAKER_EGOMAN 1 | ||||
#define PI_MAKER_MBEST 2 | |||||
#define PI_MAKER_EMBEST 2 | |||||
#define PI_MAKER_UNKNOWN 3 | #define PI_MAKER_UNKNOWN 3 | ||||
extern const char *piModelNames [16] ; | extern const char *piModelNames [16] ; | ||||
@@ -108,7 +113,7 @@ extern const int piMemorySize [ 8] ; | |||||
// Threads | // Threads | ||||
#define PI_THREAD(X) void *X (void *dummy) | |||||
#define PI_THREAD(X) void *X (UNU void *dummy) | |||||
// Failure modes | // Failure modes | ||||
@@ -168,6 +173,7 @@ extern int wiringPiFailure (int fatal, const char *message, ...) ; | |||||
extern struct wiringPiNodeStruct *wiringPiFindNode (int pin) ; | extern struct wiringPiNodeStruct *wiringPiFindNode (int pin) ; | ||||
extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) ; | extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) ; | ||||
extern void wiringPiVersion (int *major, int *minor) ; | |||||
extern int wiringPiSetup (void) ; | extern int wiringPiSetup (void) ; | ||||
extern int wiringPiSetupSys (void) ; | extern int wiringPiSetupSys (void) ; | ||||
extern int wiringPiSetupGpio (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 | // 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 void piBoardId (int *model, int *rev, int *mem, int *maker, int *overVolted) ; | ||||
extern int wpiPinToGpio (int wpiPin) ; | extern int wpiPinToGpio (int wpiPin) ; | ||||
extern int physPinToGpio (int physPin) ; | extern int physPinToGpio (int physPin) ; | ||||
@@ -52,6 +52,7 @@ | |||||
#include <string.h> | #include <string.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <asm/ioctl.h> | |||||
#include "wiringPi.h" | #include "wiringPi.h" | ||||
#include "wiringPiI2C.h" | #include "wiringPiI2C.h" | ||||
@@ -221,7 +222,7 @@ int wiringPiI2CSetup (const int devId) | |||||
int rev ; | int rev ; | ||||
const char *device ; | const char *device ; | ||||
rev = piBoardRev () ; | |||||
rev = piGpioLayout () ; | |||||
if (rev == 1) | if (rev == 1) | ||||
device = "/dev/i2c-0" ; | device = "/dev/i2c-0" ; | ||||
@@ -28,6 +28,7 @@ | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <sys/ioctl.h> | #include <sys/ioctl.h> | ||||
#include <asm/ioctl.h> | |||||
#include <linux/spi/spidev.h> | #include <linux/spi/spidev.h> | ||||
#include "wiringPi.h" | #include "wiringPi.h" | ||||
@@ -38,10 +39,10 @@ | |||||
// The SPI bus parameters | // The SPI bus parameters | ||||
// Variables as they need to be passed as pointers later on | // 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 uint32_t spiSpeeds [2] ; | ||||
static int spiFds [2] ; | static int spiFds [2] ; | ||||
@@ -49,24 +49,36 @@ int serialOpen (const char *device, const int baud) | |||||
switch (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: | default: | ||||
return -2 ; | return -2 ; | ||||
@@ -96,7 +108,7 @@ int serialOpen (const char *device, const int baud) | |||||
options.c_cc [VMIN] = 0 ; | options.c_cc [VMIN] = 0 ; | ||||
options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds) | options.c_cc [VTIME] = 100 ; // Ten seconds (100 deciseconds) | ||||
tcsetattr (fd, TCSANOW | TCSAFLUSH, &options) ; | |||||
tcsetattr (fd, TCSANOW, &options) ; | |||||
ioctl (fd, TIOCMGET, &status); | ioctl (fd, TIOCMGET, &status); | ||||
@@ -55,6 +55,10 @@ | |||||
#include "ads1115.h" | #include "ads1115.h" | ||||
#include "sn3218.h" | #include "sn3218.h" | ||||
#include "drcSerial.h" | #include "drcSerial.h" | ||||
#include "pseudoPins.h" | |||||
#include "bmp180.h" | |||||
#include "htu21d.h" | |||||
#include "ds18b20.h" | |||||
#include "wpiExtensions.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: | * doExtensionMax31855: | ||||
* Analog IO | * Analog IO | ||||
* max31855:base:spiChan | * 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) ; | sn3218Setup (pinBase) ; | ||||
return TRUE ; | return TRUE ; | ||||
@@ -677,6 +744,10 @@ static struct extensionFunctionStruct extensionFunctions [] = | |||||
{ "sr595", &doExtensionSr595 }, | { "sr595", &doExtensionSr595 }, | ||||
{ "pcf8574", &doExtensionPcf8574 }, | { "pcf8574", &doExtensionPcf8574 }, | ||||
{ "pcf8591", &doExtensionPcf8591 }, | { "pcf8591", &doExtensionPcf8591 }, | ||||
{ "bmp180", &doExtensionBmp180 }, | |||||
{ "pseudoPins", &doExtensionPseudoPins }, | |||||
{ "htu21d", &doExtensionHtu21d }, | |||||
{ "ds18b20", &doExtensionDs18b20 }, | |||||
{ "mcp3002", &doExtensionMcp3002 }, | { "mcp3002", &doExtensionMcp3002 }, | ||||
{ "mcp3004", &doExtensionMcp3004 }, | { "mcp3004", &doExtensionMcp3004 }, | ||||
{ "mcp4802", &doExtensionMcp4802 }, | { "mcp4802", &doExtensionMcp4802 }, | ||||