소스 검색

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 11 년 전
부모
커밋
13bbba7a22
15개의 변경된 파일744개의 추가작업 그리고 91개의 파일을 삭제
  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) ;
+}
+
+