diff --git a/INSTALL b/INSTALL
new file mode 100644
index 0000000..8e0c43c
--- /dev/null
+++ b/INSTALL
@@ -0,0 +1,36 @@
+
+How to install wiringPi
+=======================
+
+The easiest way is to use the supplied 'build' script:
+
+ ./build
+
+that should do a complete install or upgrade of wiringPi for you.
+
+That will install a dynamic library.
+
+Some distributions do not have /usr/local/lib in the default LD_LIBRARY_PATH. To
+fix this, you need to edit /etc/ld.so.conf and add in a single line:
+
+ /usr/local/lib
+
+then run the ldconfig command.
+
+ sudo ldconfig
+
+If you want to install a static library, you may need to do this manually:
+
+ cd wiringPi
+ make static
+ sudo make install-static
+
+
+To un-install wiringPi:
+
+ ./build uninstall
+
+Gordon Henderson
+
+projects@drogon.net
+https://projects.drogon.net/
diff --git a/examples/Makefile b/examples/Makefile
index 738d36c..3607fc8 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -35,10 +35,10 @@ LDLIBS = -lwiringPi
# Should not alter anything below this line
###############################################################################
-SRC = test1.c test2.c speed.c lcd.c wfi.c \
+SRC = test1.c test2.c speed.c lcd.c wfi.c isr.c \
piface.c gertboard.c nes.c \
pwm.c tone.c servo.c \
- delayTest.c serialRead.c okLed.c
+ delayTest.c serialRead.c serialTest.c okLed.c
OBJ = $(SRC:.c=.o)
@@ -69,6 +69,10 @@ wfi: wfi.o
@echo [link]
@$(CC) -o $@ wfi.o $(LDFLAGS) $(LDLIBS)
+isr: isr.o
+ @echo [link]
+ @$(CC) -o $@ isr.o $(LDFLAGS) $(LDLIBS)
+
piface: piface.o
@echo [link]
@$(CC) -o $@ piface.o $(LDFLAGS) $(LDLIBS) -lpthread
@@ -93,6 +97,10 @@ serialRead: serialRead.o
@echo [link]
@$(CC) -o $@ serialRead.o $(LDFLAGS) $(LDLIBS)
+serialTest: serialTest.o
+ @echo [link]
+ @$(CC) -o $@ serialTest.o $(LDFLAGS) $(LDLIBS)
+
okLed: okLed.o
@echo [link]
@$(CC) -o $@ okLed.o $(LDFLAGS) $(LDLIBS)
diff --git a/examples/isr.c b/examples/isr.c
new file mode 100644
index 0000000..2bef54a
--- /dev/null
+++ b/examples/isr.c
@@ -0,0 +1,99 @@
+/*
+ * isr.c:
+ * Wait for Interrupt test program - ISR method
+ *
+ * How to test:
+ * Use the SoC's pull-up and pull down resistors that are avalable
+ * on input pins. So compile & run this program (via sudo), then
+ * in another terminal:
+ * gpio mode 0 up
+ * gpio mode 0 down
+ * at which point it should trigger an interrupt. Toggle the pin
+ * up/down to generate more interrupts to test.
+ *
+ * Copyright (c) 2013 Gordon Henderson.
+ ***********************************************************************
+ * This file is part of wiringPi:
+ * https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ * wiringPi is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * wiringPi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with wiringPi. If not, see .
+ ***********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+
+// What GPIO input are we using?
+// This is a wiringPi pin number
+
+#define BUTTON_PIN 0
+
+// globalCounter:
+// Global variable to count interrupts
+// Should be declared volatile to make sure the compiler doesn't cache it.
+
+static volatile int globalCounter = 0 ;
+
+
+/*
+ * myInterrupt:
+ *********************************************************************************
+ */
+
+void myInterrupt (void)
+{
+ ++globalCounter ;
+}
+
+
+/*
+ *********************************************************************************
+ * main
+ *********************************************************************************
+ */
+
+int main (void)
+{
+ int myCounter = 0 ;
+
+ if (wiringPiSetup () < 0)
+ {
+ fprintf (stderr, "Unable to setup wiringPi: %s\n", strerror (errno)) ;
+ return 1 ;
+ }
+
+ if (wiringPiISR (BUTTON_PIN, INT_EDGE_FALLING, &myInterrupt) < 0)
+ {
+ fprintf (stderr, "Unable to setup ISR: %s\n", strerror (errno)) ;
+ return 1 ;
+ }
+
+
+ for (;;)
+ {
+ printf ("Waiting ... ") ; fflush (stdout) ;
+
+ while (myCounter == globalCounter)
+ delay (100) ;
+
+ printf (" Done. counter: %5d\n", globalCounter) ;
+ myCounter = globalCounter ;
+ }
+
+ return 0 ;
+}
diff --git a/examples/okLed.c b/examples/okLed.c
index 3bf21e2..02f0b22 100644
--- a/examples/okLed.c
+++ b/examples/okLed.c
@@ -17,6 +17,7 @@
#include
#include
#include
+#include
#include
#include
diff --git a/examples/serialTest.c b/examples/serialTest.c
new file mode 100644
index 0000000..85a1a66
--- /dev/null
+++ b/examples/serialTest.c
@@ -0,0 +1,57 @@
+/*
+ * serialTest.c:
+ * Very simple program to test the serial port. Expects
+ * the port to be looped back to itself
+ *
+ */
+
+#include
+#include
+#include
+
+#include
+#include
+
+int main ()
+{
+ int fd ;
+ int count ;
+ unsigned int nextTime ;
+
+ if ((fd = serialOpen ("/dev/ttyAMA0", 115200)) < 0)
+ {
+ fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
+ return 1 ;
+ }
+
+ if (wiringPiSetup () == -1)
+ {
+ fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
+ return 1 ;
+ }
+
+ nextTime = millis () + 300 ;
+
+ for (count = 0 ; count < 256 ; )
+ {
+ if (millis () > nextTime)
+ {
+ printf ("\nOut: %3d: ", count) ;
+ fflush (stdout) ;
+ serialPutchar (fd, count) ;
+ nextTime += 300 ;
+ ++count ;
+ }
+
+ delay (3) ;
+
+ while (serialDataAvail (fd))
+ {
+ printf (" -> %3d", serialGetchar (fd)) ;
+ fflush (stdout) ;
+ }
+ }
+
+ printf ("\n") ;
+ return 0 ;
+}
diff --git a/examples/wfi.c b/examples/wfi.c
index 9efcc2c..6bb6892 100644
--- a/examples/wfi.c
+++ b/examples/wfi.c
@@ -2,7 +2,17 @@
* wfi.c:
* Wait for Interrupt test program
*
- * Copyright (c) 2012 Gordon Henderson.
+ * This program demonstrates the use of the waitForInterrupt()
+ * function in wiringPi. It listens to a button input on
+ * BCM_GPIO pin 17 (wiringPi pin 0)
+ *
+ * The biggest issue with this method is that it really only works
+ * well in Sys mode.
+ *
+ * Jan 2013: This way of doing things is sort of deprecated now, see
+ * the wiringPiISR() function instead and the isr.c test program here.
+ *
+ * Copyright (c) 2012-2013 Gordon Henderson.
***********************************************************************
* This file is part of wiringPi:
* https://projects.drogon.net/raspberry-pi/wiringpi/
@@ -33,9 +43,8 @@
#define COUNT_KEY 0
// What BCM_GPIO input are we using?
-// GPIO 0 is one of the I2C pins with an on-board pull-up
-#define BUTTON_PIN 0
+#define BUTTON_PIN 17
// Debounce time in mS
@@ -63,13 +72,11 @@ PI_THREAD (waitForIt)
int debounceTime = 0 ;
(void)piHiPri (10) ; // Set this thread to be high priority
- digitalWrite (18, 1) ;
for (;;)
{
if (waitForInterrupt (BUTTON_PIN, -1) > 0) // Got it
{
-
// Bouncing?
if (millis () < debounceTime)
@@ -80,7 +87,6 @@ PI_THREAD (waitForIt)
// We have a valid one
- digitalWrite (17, state) ;
state ^= 1 ;
piLock (COUNT_KEY) ;
@@ -89,7 +95,7 @@ PI_THREAD (waitForIt)
// Wait for key to be released
- while (digitalRead (0) == LOW)
+ while (digitalRead (BUTTON_PIN) == LOW)
delay (1) ;
debounceTime = millis () + DEBOUNCE_TIME ;
@@ -108,11 +114,9 @@ void setup (void)
{
// Use the gpio program to initialise the hardware
-// (This is the crude, but effective bit)
+// (This is the crude, but effective)
- system ("gpio edge 0 falling") ;
- system ("gpio export 17 out") ;
- system ("gpio export 18 out") ;
+ system ("gpio edge 17 falling") ;
// Setup wiringPi
@@ -120,9 +124,8 @@ void setup (void)
// Fire off our interrupt handler
- piThreadCreate (waitForIt) ;
+ piThreadCreate (waitForIt) ;
- digitalWrite (17, 0) ;
}
@@ -147,7 +150,7 @@ int main (void)
piLock (COUNT_KEY) ;
myCounter = globalCounter ;
piUnlock (COUNT_KEY) ;
- delay (5000) ;
+ delay (500) ;
}
printf (" Done. myCounter: %5d\n", myCounter) ;
diff --git a/gpio/Makefile b/gpio/Makefile
index 5693c44..729a86b 100644
--- a/gpio/Makefile
+++ b/gpio/Makefile
@@ -30,7 +30,7 @@ INCLUDE = -I/usr/local/include
CFLAGS = $(DEBUG) -Wall $(INCLUDE) -Winline -pipe
LDFLAGS = -L/usr/local/lib
-LIBS = -lwiringPi
+LIBS = -lwiringPi -lpthread
# May not need to alter anything below this line
###############################################################################
diff --git a/gpio/gpio.1 b/gpio/gpio.1
index c39e5dc..a83cf9f 100644
--- a/gpio/gpio.1
+++ b/gpio/gpio.1
@@ -57,6 +57,9 @@ converters on the Gertboard. It's designed for simple testing and
diagnostic purposes, but can be used in shell scripts for general if
somewhat slow control of the GPIO pins.
+It can also control the IO's on the PiFace IO board and load the SPI and I2C
+kernel modules if required.
+
Additionally, it can be used to set the exports in the \fI/sys/class/gpio\fR
system directory to allow subsequent programs to use the \fR/sys/class/gpio\fR
interface without needing to be run as root.
@@ -70,6 +73,8 @@ Output the current version including the board revision of the Raspberry Pi.
.TP
.B \-g
Use the BCM_GPIO pins numbers rather than wiringPi pin numbers.
+\fINOTE:\fR The BCM_GPIO pin numbers are always used with the
+export and edge commands.
.TP
.B \-p
@@ -183,7 +188,7 @@ SPI digital to analogue converter.
The board jumpers need to be in-place to do this operation.
-.SH "WiringPi vs. GPIO Pin numbering"
+.SH "WiringPi vs. BCM_GPIO Pin numbering"
.PP
.TS
@@ -213,6 +218,12 @@ _
20 - 31
.TE
+Note that "r1" and "r2" above refers to the board revision. Normally
+wiringPi detects the correct board revision with use for it's own
+numbering scheme, but if you are using a Revision 2 board with some
+of the pins which change numbers between revisions you will need
+to alter your software.
+
.SH FILES
.TP 2.2i
diff --git a/gpio/gpio.c b/gpio/gpio.c
index 52fcb6f..7b84abd 100644
--- a/gpio/gpio.c
+++ b/gpio/gpio.c
@@ -35,12 +35,14 @@
#include
#include
+extern int wiringPiDebug ;
+
#ifndef TRUE
# define TRUE (1==1)
# define FALSE (1==2)
#endif
-#define VERSION "1.5"
+#define VERSION "1.6"
static int wpMode ;
@@ -127,7 +129,7 @@ static int moduleLoaded (char *modName)
static void _doLoadUsage (char *argv [])
{
- fprintf (stderr, "Usage: %s load \n", argv [0]) ;
+ fprintf (stderr, "Usage: %s load [bufferSize in KB for spi]\n", argv [0]) ;
exit (1) ;
}
@@ -136,16 +138,24 @@ static void doLoad (int argc, char *argv [])
char *module1, *module2 ;
char cmd [80] ;
char *file1, *file2 ;
+ char spiBuf [32] ;
- if (argc != 3)
+ if (argc < 3)
_doLoadUsage (argv) ;
+ spiBuf [0] = 0 ;
+
/**/ if (strcasecmp (argv [2], "spi") == 0)
{
module1 = "spidev" ;
module2 = "spi_bcm2708" ;
file1 = "/dev/spidev0.0" ;
file2 = "/dev/spidev0.1" ;
+ if (argc == 4)
+ sprintf (spiBuf, " bufsize=%d", atoi (argv [3]) * 1024) ;
+ else if (argc > 4)
+ _doLoadUsage (argv) ;
+
}
else if (strcasecmp (argv [2], "i2c") == 0)
{
@@ -159,7 +169,7 @@ static void doLoad (int argc, char *argv [])
if (!moduleLoaded (module1))
{
- sprintf (cmd, "modprobe %s", module1) ;
+ sprintf (cmd, "modprobe %s%s", module1, spiBuf) ;
system (cmd) ;
}
@@ -848,6 +858,12 @@ int main (int argc, char *argv [])
{
int i ;
+ if (getenv ("WIRINGPI_DEBUG") != NULL)
+ {
+ printf ("gpio: wiringPi debug mode enabled\n") ;
+ wiringPiDebug = TRUE ;
+ }
+
if (argc == 1)
{
fprintf (stderr, "%s\n", usage) ;
diff --git a/wiringPi/Makefile b/wiringPi/Makefile
index e18a654..62e9d9b 100644
--- a/wiringPi/Makefile
+++ b/wiringPi/Makefile
@@ -1,4 +1,4 @@
-#
+# ;
# Makefile:
# wiringPi - Wiring Compatable library for the Raspberry Pi
#
@@ -45,13 +45,15 @@ LIBS =
SRC = wiringPi.c wiringPiFace.c wiringSerial.c wiringShift.c \
gertboard.c \
piNes.c \
- lcd.c piHiPri.c piThread.c wiringPiSPI.c \
+ lcd.c piHiPri.c piThread.c \
+ wiringPiSPI.c wiringPiI2C.c \
softPwm.c softServo.c softTone.c
OBJ = $(SRC:.c=.o)
-all: $(STATIC) $(DYNAMIC)
-#all: $(DYNAMIC)
+all: $(DYNAMIC)
+
+static: $(STATIC)
$(STATIC): $(OBJ)
@echo "[Link (Static)]"
@@ -77,7 +79,7 @@ tags: $(SRC)
@ctags $(SRC)
.PHONEY: install
-install: $(TARGET)
+install: $(DYNAMIC)
@echo "[Install]"
@install -m 0755 -d $(DESTDIR)$(PREFIX)/lib
@install -m 0755 -d $(DESTDIR)$(PREFIX)/include
@@ -91,12 +93,17 @@ install: $(TARGET)
@install -m 0644 softTone.h $(DESTDIR)$(PREFIX)/include
@install -m 0644 lcd.h $(DESTDIR)$(PREFIX)/include
@install -m 0644 wiringPiSPI.h $(DESTDIR)$(PREFIX)/include
- @install -m 0755 libwiringPi.a $(DESTDIR)$(PREFIX)/lib
+ @install -m 0644 wiringPiI2C.h $(DESTDIR)$(PREFIX)/include
@install -m 0755 libwiringPi.so.$(VERSION) $(DESTDIR)$(PREFIX)/lib
@ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)/lib/libwiringPi.so
@ln -sf $(DESTDIR)$(PREFIX)/lib/libwiringPi.so.$(VERSION) $(DESTDIR)/lib/libwiringPi.so.1
@ldconfig
+.PHONEY: install-static
+install-static: $(STATIC)
+ @echo "[Install Static]"
+ @install -m 0755 libwiringPi.a $(DESTDIR)$(PREFIX)/lib
+
.PHONEY: uninstall
uninstall:
@echo "[UnInstall]"
@@ -110,6 +117,7 @@ uninstall:
@rm -f $(DESTDIR)$(PREFIX)/include/softTone.h
@rm -f $(DESTDIR)$(PREFIX)/include/lcd.h
@rm -f $(DESTDIR)$(PREFIX)/include/wiringPiSPI.h
+ @rm -f $(DESTDIR)$(PREFIX)/include/wiringPiI2C.h
@rm -f $(DESTDIR)$(PREFIX)/lib/libwiringPi.*
@ldconfig
diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c
index df4d969..cfb6705 100644
--- a/wiringPi/wiringPi.c
+++ b/wiringPi/wiringPi.c
@@ -65,10 +65,12 @@
#include
#include
#include
+#include
#include
#include
#include
#include
+#include
#include "wiringPi.h"
@@ -173,9 +175,17 @@ static volatile uint32_t *pads ;
static volatile uint32_t *timer ;
static volatile uint32_t *timerIrqRaw ;
+// Time for easy calculations
+
+static unsigned long long epoch ;
+
+// Misc
+
+static int wiringPiMode = WPI_MODE_UNINITIALISED ;
+
// Debugging
-static int wiringPiDebug = FALSE ;
+int wiringPiDebug = FALSE ;
// The BCM2835 has 54 GPIO pins.
// BCM2835 data sheet, Page 90 onwards.
@@ -200,6 +210,11 @@ static int wiringPiDebug = FALSE ;
static int sysFds [64] ;
+// ISR Data
+
+static void (*isrFunctions [64])(void) ;
+
+
// Doing it the Arduino way with lookup tables...
// Yes, it's probably more innefficient than all the bit-twidling, but it
// does tend to make it all a bit clearer. At least to me!
@@ -370,10 +385,6 @@ static uint8_t gpioToPwmPort [] =
} ;
-// Time for easy calculations
-
-static unsigned long long epoch ;
-
/*
* Functions
*********************************************************************************
@@ -418,6 +429,15 @@ int wpiPinToGpio (int wpiPin)
*********************************************************************************
*/
+static void piBoardRevOops (char *why)
+{
+ fprintf (stderr, "piBoardRev: Unable to determine board revision from /proc/cpuinfo\n") ;
+ fprintf (stderr, " -> %s\n", why) ;
+ fprintf (stderr, " -> You may want to check:\n") ;
+ fprintf (stderr, " -> http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ;
+ exit (EXIT_FAILURE) ;
+}
+
int piBoardRev (void)
{
FILE *cpuFd ;
@@ -440,24 +460,19 @@ int piBoardRev (void)
fclose (cpuFd) ;
if (line == NULL)
- {
- fprintf (stderr, "piBoardRev: Unable to determine board revision from /proc/cpuinfo\n") ;
- fprintf (stderr, " (No \"Revision\" line)\n") ;
- errno = 0 ;
- return -1 ;
- }
+ piBoardRevOops ("No \"Revision\" line") ;
+
+ line [strlen (line) - 1] = 0 ; // Chomp LF
+ if (wiringPiDebug)
+ printf ("piboardRev: Revision string: %s\n", line) ;
+
for (c = line ; *c ; ++c)
if (isdigit (*c))
break ;
if (!isdigit (*c))
- {
- fprintf (stderr, "piBoardRev: Unable to determine board revision from /proc/cpuinfo\n") ;
- fprintf (stderr, " (No numeric revision string in: \"%s\"\n", line) ;
- errno = 0 ;
- return -1 ;
- }
+ piBoardRevOops ("No numeric revision string") ;
// If you have overvolted the Pi, then it appears that the revision
// has 100000 added to it!
@@ -466,26 +481,18 @@ int piBoardRev (void)
if (strlen (c) != 4)
printf ("piboardRev: This Pi has/is overvolted!\n") ;
- lastChar = c [strlen (c) - 2] ;
+ lastChar = line [strlen (line) - 1] ;
+
+ if (wiringPiDebug)
+ printf ("piboardRev: lastChar is: '%c' (%d, 0x%02X)\n", lastChar, lastChar, lastChar) ;
/**/ if ((lastChar == '2') || (lastChar == '3'))
boardRev = 1 ;
else
boardRev = 2 ;
-#ifdef DO_WE_CARE_ABOUT_THIS_NOW
- else
- {
- fprintf (stderr, "WARNING: wiringPi: Unable to determine board revision from \"%d\"\n", r) ;
- fprintf (stderr, " -> You may want to check:\n") ;
- fprintf (stderr, " -> http://www.raspberrypi.org/phpBB3/viewtopic.php?p=184410#p184410\n") ;
- fprintf (stderr, " -> Assuming a Rev 1 board\n") ;
- boardRev = 1 ;
- }
-#endif
-
if (wiringPiDebug)
- printf ("piboardRev: Revision string: %s, board revision: %d\n", c, boardRev) ;
+ printf ("piBoardRev: Returning revision: %d\n", boardRev) ;
return boardRev ;
}
@@ -741,11 +748,11 @@ void digitalWriteByteGpio (int value)
else
pinSet |= (1 << pinToGpio [pin]) ;
- *(gpio + gpioToGPCLR [0]) = pinClr ;
- *(gpio + gpioToGPSET [0]) = pinSet ;
-
mask <<= 1 ;
}
+
+ *(gpio + gpioToGPCLR [0]) = pinClr ;
+ *(gpio + gpioToGPSET [0]) = pinSet ;
}
void digitalWriteByteSys (int value)
@@ -944,6 +951,99 @@ int waitForInterruptGpio (int pin, int mS)
/*
+ * interruptHandler:
+ * This is a thread and gets started to wait for the interrupt we're
+ * hoping to catch. It will call the user-function when the interrupt
+ * fires.
+ *********************************************************************************
+ */
+
+static void *interruptHandler (void *arg)
+{
+ int myPin = *(int *)arg ;
+
+ (void)piHiPri (55) ; // Only effective if we run as root
+
+ for (;;)
+ if (waitForInterruptSys (myPin, -1) > 0)
+ isrFunctions [myPin] () ;
+
+ return NULL ;
+}
+
+
+/*
+ * wiringPiISR:
+ * Take the details and create an interrupt handler that will do a call-
+ * back to the user supplied function.
+ *********************************************************************************
+ */
+
+int wiringPiISR (int pin, int mode, void (*function)(void))
+{
+ pthread_t threadId ;
+ char fName [64] ;
+ char *modeS ;
+ char pinS [8] ;
+ pid_t pid ;
+
+ pin &= 63 ;
+
+ if (wiringPiMode == WPI_MODE_UNINITIALISED)
+ {
+ fprintf (stderr, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ;
+ exit (EXIT_FAILURE) ;
+ }
+ else if (wiringPiMode == WPI_MODE_PINS)
+ pin = pinToGpio [pin] ;
+
+// Now export the pin and set the right edge
+// We're going to use the gpio program to do this, so it assumes
+// a full installation of wiringPi. It's a bit 'clunky', but it
+// is a way that will work when we're running in "Sys" mode, as
+// a non-root user. (without sudo)
+
+ if (mode != INT_EDGE_SETUP)
+ {
+ /**/ if (mode == INT_EDGE_FALLING)
+ modeS = "falling" ;
+ else if (mode == INT_EDGE_RISING)
+ modeS = "rising" ;
+ else
+ modeS = "both" ;
+
+ sprintf (pinS, "%d", pin) ;
+
+ if ((pid = fork ()) < 0) // Fail
+ return pid ;
+
+ if (pid == 0) // Child, exec
+ {
+ execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ;
+ return -1 ; // Failure ...
+ }
+ else // Parent, wait
+ wait (NULL) ;
+ }
+
+// Now pre-open the /sys/class node - it may already be open if
+// we had set it up earlier, but this will do no harm.
+
+ sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
+ if ((sysFds [pin] = open (fName, O_RDWR)) < 0)
+ return -1 ;
+
+ isrFunctions [pin] = function ;
+
+ pthread_create (&threadId, NULL, interruptHandler, &pin) ;
+
+ delay (1) ;
+
+ return 0 ;
+}
+
+
+/*
* delay:
* Wait for some number of milli seconds
*********************************************************************************
@@ -1064,8 +1164,17 @@ int wiringPiSetup (void)
uint8_t *gpioMem, *pwmMem, *clkMem, *padsMem, *timerMem ;
struct timeval tv ;
+ if (geteuid () != 0)
+ {
+ fprintf (stderr, "Must be root to call wiringPiSetup(). (Did you forget sudo?)\n") ;
+ exit (EXIT_FAILURE) ;
+ }
+
if (getenv ("WIRINGPI_DEBUG") != NULL)
+ {
+ printf ("wiringPi: Debug mode enabled\n") ;
wiringPiDebug = TRUE ;
+ }
if (wiringPiDebug)
printf ("wiringPi: wiringPiSetup called\n") ;
@@ -1083,8 +1192,7 @@ int wiringPiSetup (void)
pwmSetRange = pwmSetRangeWPi ;
pwmSetClock = pwmSetClockWPi ;
- if ((boardRev = piBoardRev ()) < 0)
- return -1 ;
+ boardRev = piBoardRev () ;
if (boardRev == 1)
pinToGpio = pinToGpioR1 ;
@@ -1105,7 +1213,8 @@ int wiringPiSetup (void)
if ((gpioMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
{
- fprintf (stderr, "wiringPiSetup: malloc failed: %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ fprintf (stderr, "wiringPiSetup: malloc failed: %s\n", strerror (errno)) ;
return -1 ;
}
@@ -1118,7 +1227,8 @@ int wiringPiSetup (void)
if ((int32_t)gpio < 0)
{
- fprintf (stderr, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ fprintf (stderr, "wiringPiSetup: mmap failed: %s\n", strerror (errno)) ;
return -1 ;
}
@@ -1126,7 +1236,8 @@ int wiringPiSetup (void)
if ((pwmMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
{
- fprintf (stderr, "wiringPiSetup: pwmMem malloc failed: %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ fprintf (stderr, "wiringPiSetup: pwmMem malloc failed: %s\n", strerror (errno)) ;
return -1 ;
}
@@ -1137,7 +1248,8 @@ int wiringPiSetup (void)
if ((int32_t)pwm < 0)
{
- fprintf (stderr, "wiringPiSetup: mmap failed (pwm): %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ fprintf (stderr, "wiringPiSetup: mmap failed (pwm): %s\n", strerror (errno)) ;
return -1 ;
}
@@ -1145,7 +1257,8 @@ int wiringPiSetup (void)
if ((clkMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
{
- fprintf (stderr, "wiringPiSetup: clkMem malloc failed: %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ fprintf (stderr, "wiringPiSetup: clkMem malloc failed: %s\n", strerror (errno)) ;
return -1 ;
}
@@ -1156,7 +1269,8 @@ int wiringPiSetup (void)
if ((int32_t)clk < 0)
{
- fprintf (stderr, "wiringPiSetup: mmap failed (clk): %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ fprintf (stderr, "wiringPiSetup: mmap failed (clk): %s\n", strerror (errno)) ;
return -1 ;
}
@@ -1164,7 +1278,8 @@ int wiringPiSetup (void)
if ((padsMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
{
- fprintf (stderr, "wiringPiSetup: padsMem malloc failed: %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ fprintf (stderr, "wiringPiSetup: padsMem malloc failed: %s\n", strerror (errno)) ;
return -1 ;
}
@@ -1175,7 +1290,8 @@ int wiringPiSetup (void)
if ((int32_t)pads < 0)
{
- fprintf (stderr, "wiringPiSetup: mmap failed (pads): %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ fprintf (stderr, "wiringPiSetup: mmap failed (pads): %s\n", strerror (errno)) ;
return -1 ;
}
@@ -1188,7 +1304,8 @@ int wiringPiSetup (void)
if ((timerMem = malloc (BLOCK_SIZE + (PAGE_SIZE-1))) == NULL)
{
- fprintf (stderr, "wiringPiSetup: timerMem malloc failed: %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ fprintf (stderr, "wiringPiSetup: timerMem malloc failed: %s\n", strerror (errno)) ;
return -1 ;
}
@@ -1199,7 +1316,8 @@ int wiringPiSetup (void)
if ((int32_t)timer < 0)
{
- fprintf (stderr, "wiringPiSetup: mmap failed (timer): %s\n", strerror (errno)) ;
+ if (wiringPiDebug)
+ fprintf (stderr, "wiringPiSetup: mmap failed (timer): %s\n", strerror (errno)) ;
return -1 ;
}
@@ -1216,6 +1334,8 @@ int wiringPiSetup (void)
gettimeofday (&tv, NULL) ;
epoch = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ;
+ wiringPiMode = WPI_MODE_PINS ;
+
return 0 ;
}
@@ -1233,12 +1353,18 @@ int wiringPiSetupGpio (void)
{
int x ;
- if (wiringPiDebug)
- printf ("wiringPi: wiringPiSetupGpio called\n") ;
+ if (geteuid () != 0)
+ {
+ fprintf (stderr, "Must be root to call wiringPiSetupGpio(). (Did you forget sudo?)\n") ;
+ exit (EXIT_FAILURE) ;
+ }
if ((x = wiringPiSetup ()) < 0)
return x ;
+ if (wiringPiDebug)
+ printf ("wiringPi: wiringPiSetupGpio called\n") ;
+
pinMode = pinModeGpio ;
pullUpDnControl = pullUpDnControlGpio ;
digitalWrite = digitalWriteGpio ;
@@ -1252,6 +1378,8 @@ int wiringPiSetupGpio (void)
pwmSetRange = pwmSetRangeWPi ;
pwmSetClock = pwmSetClockWPi ;
+ wiringPiMode = WPI_MODE_GPIO ;
+
return 0 ;
}
@@ -1272,6 +1400,9 @@ int wiringPiSetupSys (void)
struct timeval tv ;
char fName [128] ;
+ if (getenv ("WIRINGPI_DEBUG") != NULL)
+ wiringPiDebug = TRUE ;
+
if (wiringPiDebug)
printf ("wiringPi: wiringPiSetupSys called\n") ;
@@ -1288,15 +1419,13 @@ int wiringPiSetupSys (void)
pwmSetRange = pwmSetRangeSys ;
pwmSetClock = pwmSetClockSys ;
- if ((boardRev = piBoardRev ()) < 0)
- return -1 ;
+ boardRev = piBoardRev () ;
if (boardRev == 1)
pinToGpio = pinToGpioR1 ;
else
pinToGpio = pinToGpioR2 ;
-
// Open and scan the directory, looking for exported GPIOs, and pre-open
// the 'value' interface to speed things up for later
@@ -1311,5 +1440,7 @@ int wiringPiSetupSys (void)
gettimeofday (&tv, NULL) ;
epoch = (tv.tv_sec * 1000000 + tv.tv_usec) / 1000 ;
+ wiringPiMode = WPI_MODE_GPIO_SYS ;
+
return 0 ;
}
diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h
index 6a7278e..424e3bc 100644
--- a/wiringPi/wiringPi.h
+++ b/wiringPi/wiringPi.h
@@ -23,32 +23,44 @@
// Handy defines
+// Deprecated
#define NUM_PINS 17
#define WPI_MODE_PINS 0
#define WPI_MODE_GPIO 1
#define WPI_MODE_GPIO_SYS 2
#define WPI_MODE_PIFACE 3
+#define WPI_MODE_UNINITIALISED -1
-#define INPUT 0
-#define OUTPUT 1
-#define PWM_OUTPUT 2
+#define INPUT 0
+#define OUTPUT 1
+#define PWM_OUTPUT 2
-#define LOW 0
-#define HIGH 1
+#define LOW 0
+#define HIGH 1
-#define PUD_OFF 0
-#define PUD_DOWN 1
-#define PUD_UP 2
+#define PUD_OFF 0
+#define PUD_DOWN 1
+#define PUD_UP 2
// PWM
-#define PWM_MODE_MS 0
-#define PWM_MODE_BAL 1
+#define PWM_MODE_MS 0
+#define PWM_MODE_BAL 1
+
+// Interrupt levels
+
+#define INT_EDGE_SETUP 0
+#define INT_EDGE_FALLING 1
+#define INT_EDGE_RISING 2
+
+// Threads
+
+#define PI_THREAD(X) void *X (void *dummy)
// Function prototypes
-// c++ wrappers thanks to a commend by Nick Lott
+// c++ wrappers thanks to a comment by Nick Lott
// (and others on the Raspberry Pi forums)
#ifdef __cplusplus
@@ -82,11 +94,10 @@ extern void (*pwmSetClock) (int divisor) ;
// Interrupts
extern int (*waitForInterrupt) (int pin, int mS) ;
+extern int wiringPiISR (int pin, int mode, void (*function)(void)) ;
// Threads
-#define PI_THREAD(X) void *X (void *dummy)
-
extern int piThreadCreate (void *(*fn)(void *)) ;
extern void piLock (int key) ;
extern void piUnlock (int key) ;
diff --git a/wiringPi/wiringPiI2C.c b/wiringPi/wiringPiI2C.c
new file mode 100644
index 0000000..93fe1d3
--- /dev/null
+++ b/wiringPi/wiringPiI2C.c
@@ -0,0 +1,122 @@
+/*
+ * wiringPiI2C.c:
+ * Simplified I2C access routines
+ * Copyright (c) 2013 Gordon Henderson
+ ***********************************************************************
+ * This file is part of wiringPi:
+ * https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ * wiringPi is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * wiringPi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with wiringPi.
+ * If not, see .
+ ***********************************************************************
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#include "wiringPi.h"
+#include "wiringPiI2C.h"
+
+
+/*
+ * wiringPiI2CRead:
+ * Simple device read
+ *********************************************************************************
+ */
+
+int wiringPiI2CRead (int fd)
+{
+ return i2c_smbus_read_byte (fd) ;
+}
+
+
+/*
+ * wiringPiI2CReadReg8: wiringPiI2CReadReg16:
+ * Read an 8 or 16-bit value from a regsiter on the device
+ *********************************************************************************
+ */
+
+int wiringPiI2CReadReg8 (int fd, int reg)
+{
+ return i2c_smbus_read_byte_data (fd, reg) ;
+}
+
+int wiringPiI2CReadReg16 (int fd, int reg)
+{
+ return i2c_smbus_read_word_data (fd, reg) ;
+}
+
+
+/*
+ * wiringPiI2CWrite:
+ * Simple device write
+ *********************************************************************************
+ */
+
+int wiringPiI2CWrite (int fd, int data)
+{
+ return i2c_smbus_write_byte (fd, data) ;
+}
+
+
+/*
+ * wiringPiI2CWriteReg8: wiringPiI2CWriteReg16:
+ * Write an 8 or 16-bit value to the given register
+ *********************************************************************************
+ */
+
+int wiringPiI2CWriteReg8 (int fd, int reg, int data)
+{
+ return i2c_smbus_write_byte_data (fd, reg, data) ;
+}
+
+int wiringPiI2CWriteReg16 (int fd, int reg, int data)
+{
+ return i2c_smbus_write_word_data (fd, reg, data) ;
+}
+
+
+/*
+ * wiringPiI2CSetup:
+ * Open the I2C device, and regsiter the target device
+ *********************************************************************************
+ */
+
+int wiringPiI2CSetup (int devId)
+{
+ int rev, fd ;
+ char *device ;
+
+ if ((rev = piBoardRev ()) < 0)
+ {
+ fprintf (stderr, "wiringPiI2CSetup: Unable to determine Pi board revision\n") ;
+ exit (1) ;
+ }
+
+ if (rev == 1)
+ device = "/dev/i2c-0" ;
+ else
+ device = "/dev/i2c-1" ;
+
+ if ((fd = open (device, O_RDWR)) < 0)
+ return -1 ;
+
+ if (ioctl (fd, I2C_SLAVE, devId) < 0)
+ return -1 ;
+
+ return fd ;
+}
diff --git a/wiringPi/wiringPiI2C.h b/wiringPi/wiringPiI2C.h
new file mode 100644
index 0000000..6710ff4
--- /dev/null
+++ b/wiringPi/wiringPiI2C.h
@@ -0,0 +1,41 @@
+/*
+ * wiringPiI2C.h:
+ * Simplified I2C access routines
+ * Copyright (c) 2013 Gordon Henderson
+ ***********************************************************************
+ * This file is part of wiringPi:
+ * https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ * wiringPi is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * wiringPi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with wiringPi.
+ * If not, see .
+ ***********************************************************************
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern int wiringPiI2CRead (int fd) ;
+extern int wiringPiI2CReadReg8 (int fd, int reg) ;
+extern int wiringPiI2CReadReg16 (int fd, int reg) ;
+
+extern int wiringPiI2CWrite (int fd, int data) ;
+extern int wiringPiI2CWriteReg8 (int fd, int reg, int data) ;
+extern int wiringPiI2CWriteReg16 (int fd, int reg, int data) ;
+
+int wiringPiI2CSetup (int devId) ;
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/wiringPi/wiringPiISR.c b/wiringPi/wiringPiISR.c
new file mode 100644
index 0000000..9e847cc
--- /dev/null
+++ b/wiringPi/wiringPiISR.c
@@ -0,0 +1,109 @@
+/*
+ * wiringPiISR.c:
+ * Simplified Interrupt Service Routine handling
+ * Copyright (c) 2013 Gordon Henderson
+ ***********************************************************************
+ * This file is part of wiringPi:
+ * https://projects.drogon.net/raspberry-pi/wiringpi/
+ *
+ * wiringPi is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * wiringPi is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with wiringPi.
+ * If not, see .
+ ***********************************************************************
+ */
+
+#include
+#include
+#include
+
+#include "wiringPi.h"
+
+
+
+static void (*isrFunctions [64])(void) ;
+static int isrFds [64] ;
+
+/*
+ * interruptHandler:
+ * This is a thread and gets started to wait for the interrupt we're
+ * hoping to catch. It will call the user-function when the interrupt
+ * fires.
+ *********************************************************************************
+ */
+
+static void *interruptHandler (void *arg)
+{
+ int pin = *(int *)arg ;
+
+ (void)piHiPri (55) ;
+
+ for (;;)
+ {
+ if (waitForInterrupt (pin, -1) > 0)
+ isrFunctions [pin] () ;
+ }
+
+ return NULL ;
+}
+
+/*
+ * wiringPiISR:
+ * Take the details and create an interrupt handler that will do a call-
+ * back to the user supplied function.
+ *********************************************************************************
+ */
+
+int wiringPiISR (int pin, int mode, void (*function)(void))
+{
+ pthread_t threadId ;
+ char command [64] ;
+
+ pin &= 63 ;
+
+ if (wiringPiMode == WPI_MODE_UNINITIALISED)
+ {
+ fprintf (stderr, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ;
+ exit (EXIT_FAILURE) ;
+ }
+ else if (wiringPiMode == WPI_MODE_PINS)
+ pin = pinToGpio [pin] ;
+
+
+ isrFunctions [pin] = function ;
+
+// Now export the pin and set the right edge
+
+ if (mode != INT_EDGE_SETUP)
+ {
+ /**/ if (mode == INT_EDGE_FALLING)
+ modes = "falling" ;
+ else if (mode == INT_EDGE_RISING)
+ modes = "rising" ;
+ else
+ modes = "both" ;
+
+ sprintf (command, "/usr/local/bin/gpio edge %d %s", pin, modes) ;
+ system (command) ;
+ }
+
+ sprintf (fName, "/sys/class/gpio/gpio%d/value", pin) ;
+ if ((isrFds [pin] = open (fName, O_RDWR)) < 0)
+ return -1 ;
+
+ {
+ fprintf ("std
+
+ pthread_create (&threadId, NULL, interruptHandler, &pin) ;
+}
+
+