Gordons Projects

--> Projects Top-Level GIT

Lots of changes here. Added new I2C test code, a new serialTest program,
authorGordon Henderson <projects@drogon.net>
Mon, 14 Jan 2013 11:31:56 +0000 (11:31 +0000)
committerGordon Henderson <projects@drogon.net>
Mon, 14 Jan 2013 11:31:56 +0000 (11:31 +0000)
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!)

15 files changed:
INSTALL [new file with mode: 0644]
examples/Makefile
examples/isr.c [new file with mode: 0644]
examples/okLed.c
examples/serialTest.c [new file with mode: 0644]
examples/wfi.c
gpio/Makefile
gpio/gpio.1
gpio/gpio.c
wiringPi/Makefile
wiringPi/wiringPi.c
wiringPi/wiringPi.h
wiringPi/wiringPiI2C.c [new file with mode: 0644]
wiringPi/wiringPiI2C.h [new file with mode: 0644]
wiringPi/wiringPiISR.c [new file with mode: 0644]

diff --git a/INSTALL b/INSTALL
new file mode 100644 (file)
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/
index 738d36c..3607fc8 100644 (file)
@@ -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 (file)
index 0000000..2bef54a
--- /dev/null
@@ -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 ;
+}
index 3bf21e2..02f0b22 100644 (file)
@@ -17,6 +17,7 @@
 #include <string.h>
 #include <fcntl.h>
 #include <unistd.h>
+#include <math.h>
 
 #include <wiringPi.h>
 #include <softPwm.h>
diff --git a/examples/serialTest.c b/examples/serialTest.c
new file mode 100644 (file)
index 0000000..85a1a66
--- /dev/null
@@ -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 ;
+}
index 9efcc2c..6bb6892 100644 (file)
@@ -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) ;
index 5693c44..729a86b 100644 (file)
@@ -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
 ###############################################################################
index c39e5dc..a83cf9f 100644 (file)
@@ -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
index 52fcb6f..7b84abd 100644 (file)
 #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) ;
index e18a654..62e9d9b 100644 (file)
@@ -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
 
index df4d969..cfb6705 100644 (file)
 #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)
@@ -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 ;
 }
index 6a7278e..424e3bc 100644 (file)
 
 // 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 (file)
index 0000000..93fe1d3
--- /dev/null
@@ -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 ;
+}
diff --git a/wiringPi/wiringPiI2C.h b/wiringPi/wiringPiI2C.h
new file mode 100644 (file)
index 0000000..6710ff4
--- /dev/null
@@ -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
diff --git a/wiringPi/wiringPiISR.c b/wiringPi/wiringPiISR.c
new file mode 100644 (file)
index 0000000..9e847cc
--- /dev/null
@@ -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) ;
+}
+
+