Explorar el Código

Lots of changes here. Added new I2C test code, a new serialTest program,
and developed the new ISR - Interrupt Service Routine
handler - much easier than the old waitForInterrupt code!

Minor tweaks to the gpio program to recognise the environment variable
WIRINGPI_DEBUG too, and removed the printing of the errors from the
main wiringPi setup routines (and added some new ones!)

Gordon Henderson hace 11 años
padre
commit
13bbba7a22
Se han modificado 15 ficheros con 744 adiciones y 91 borrados
  1. 36 0
      INSTALL
  2. 10 2
      examples/Makefile
  3. 99 0
      examples/isr.c
  4. 1 0
      examples/okLed.c
  5. 57 0
      examples/serialTest.c
  6. 17 14
      examples/wfi.c
  7. 1 1
      gpio/Makefile
  8. 12 1
      gpio/gpio.1
  9. 20 4
      gpio/gpio.c
  10. 14 6
      wiringPi/Makefile
  11. 181 50
      wiringPi/wiringPi.c
  12. 24 13
      wiringPi/wiringPi.h
  13. 122 0
      wiringPi/wiringPiI2C.c
  14. 41 0
      wiringPi/wiringPiI2C.h
  15. 109 0
      wiringPi/wiringPiISR.c

+ 36 - 0
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/

+ 10 - 2
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)

+ 99 - 0
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 <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <wiringPi.h>
+
+
+// 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 ;
+}

+ 1 - 0
examples/okLed.c

@@ -17,6 +17,7 @@
 #include <string.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <math.h>
 
 #include <wiringPi.h>
 #include <softPwm.h>

+ 57 - 0
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 <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <wiringPi.h>
+#include <wiringSerial.h>
+
+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 ;
+}

+ 17 - 14
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) ;

+ 1 - 1
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
 ###############################################################################

+ 12 - 1
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

+ 20 - 4
gpio/gpio.c

@@ -35,12 +35,14 @@
 #include <wiringPi.h>
 #include <gertboard.h>
 
+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 <spi/i2c>\n", argv [0]) ;
+  fprintf (stderr, "Usage: %s load <spi/i2c> [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) ;

+ 14 - 6
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
 

+ 181 - 50
wiringPi/wiringPi.c

@@ -65,10 +65,12 @@
 #include <string.h>
 #include <time.h>
 #include <fcntl.h>
+#include <pthread.h>
 #include <sys/time.h>
 #include <sys/mman.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/wait.h>
 
 #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)
@@ -943,6 +950,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 ;
 }

+ 24 - 13
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) ;

+ 122 - 0
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 <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/i2c-dev.h>
+
+#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 ;
+}

+ 41 - 0
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 <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#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

+ 109 - 0
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 <http://www.gnu.org/licenses/>.
+ ***********************************************************************
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+
+#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) ;
+}
+
+