chiark / gitweb /
changed to pin mode to support softPwm.
[wiringPi.git] / wiringPi / wiringPi.c
index b8e381a27cd819f809f69974473c165e57a8986a..4660a67b47b2c21a9a60a2f8548d6f8b4d2548b4 100644 (file)
@@ -70,6 +70,8 @@
 #include <sys/wait.h>
 #include <sys/ioctl.h>
 
+#include "softPwm.h"
+
 #include "wiringPi.h"
 
 #ifndef        TRUE
@@ -88,7 +90,7 @@
 
 #define        PI_GPIO_MASK    (0xFFFFFFC0)
 
-static struct wiringPiNodeStruct *wiringPiNodes = NULL ;
+struct wiringPiNodeStruct *wiringPiNodes = NULL ;
 
 // BCM Magic
 
@@ -118,7 +120,6 @@ static struct wiringPiNodeStruct *wiringPiNodes = NULL ;
 #define        FSEL_INPT               0b000
 #define        FSEL_OUTP               0b001
 #define        FSEL_ALT0               0b100
-#define        FSEL_ALT0               0b100
 #define        FSEL_ALT1               0b101
 #define        FSEL_ALT2               0b110
 #define        FSEL_ALT3               0b111
@@ -213,7 +214,13 @@ int wiringPiReturnCodes = FALSE ;
 // sysFds:
 //     Map a file descriptor from the /sys/class/gpio/gpioX/value
 
-static int sysFds [64] ;
+static int sysFds [64] =
+{
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+} ;
 
 // ISR Data
 
@@ -833,7 +840,7 @@ void gpioClockSet (int pin, int freq)
  *********************************************************************************
  */
 
-static struct wiringPiNodeStruct *wiringPiFindNode (int pin)
+struct wiringPiNodeStruct *wiringPiFindNode (int pin)
 {
   struct wiringPiNodeStruct *node = wiringPiNodes ;
 
@@ -919,6 +926,32 @@ void pinEnableED01Pi (int pin)
  *********************************************************************************
  */
 
+/*
+ * pinModeAlt:
+ *     This is an un-documented special to let you set any pin to any mode
+ *********************************************************************************
+ */
+
+void pinModeAlt (int pin, int mode)
+{
+  int fSel, shift ;
+
+  if ((pin & PI_GPIO_MASK) == 0)               // On-board pin
+  {
+    /**/ if (wiringPiMode == WPI_MODE_PINS)
+      pin = pinToGpio [pin] ;
+    else if (wiringPiMode == WPI_MODE_PHYS)
+      pin = physToGpio [pin] ;
+    else if (wiringPiMode != WPI_MODE_GPIO)
+      return ;
+
+    fSel  = gpioToGPFSEL [pin] ;
+    shift = gpioToShift  [pin] ;
+
+    *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | ((mode & 0x7) << shift) ;
+  }
+}
+
 
 /*
  * pinMode:
@@ -930,6 +963,7 @@ void pinMode (int pin, int mode)
 {
   int    fSel, shift, alt ;
   struct wiringPiNodeStruct *node = wiringPiNodes ;
+  int origPin = pin ;
 
   if ((pin & PI_GPIO_MASK) == 0)               // On-board pin
   {
@@ -940,6 +974,8 @@ void pinMode (int pin, int mode)
     else if (wiringPiMode != WPI_MODE_GPIO)
       return ;
 
+    softPwmStop (origPin) ;
+
     fSel    = gpioToGPFSEL [pin] ;
     shift   = gpioToShift  [pin] ;
 
@@ -947,9 +983,11 @@ void pinMode (int pin, int mode)
       *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) ; // Sets bits to zero = input
     else if (mode == OUTPUT)
       *(gpio + fSel) = (*(gpio + fSel) & ~(7 << shift)) | (1 << shift) ;
+    else if (mode == SOFT_PWM_OUTPUT)
+      softPwmCreate (origPin, 0, 100) ;
     else if (mode == PWM_OUTPUT)
     {
-      if ((alt = gpioToPwmALT [pin]) == 0)     // Not a PWM pin
+      if ((alt = gpioToPwmALT [pin]) == 0)     // Not a hardware capable PWM pin
        return ;
 
 // Set pin to PWM mode
@@ -959,7 +997,7 @@ void pinMode (int pin, int mode)
 
       pwmSetMode  (PWM_MODE_BAL) ;     // Pi default mode
       pwmSetRange (1024) ;             // Default range of 1024
-      pwmSetClock (32) ;                       // 19.2 / 32 = 600KHz - Also starts the PWM
+      pwmSetClock (32) ;               // 19.2 / 32 = 600KHz - Also starts the PWM
     }
     else if (mode == GPIO_CLOCK)
     {
@@ -1304,7 +1342,8 @@ int wiringPiISR (int pin, int mode, void (*function)(void))
   char  c ;
   int   bcmGpioPin ;
 
-  pin &= 63 ;
+  if ((pin < 0) || (pin > 63))
+    return wiringPiFailure (WPI_FATAL, "wiringPiISR: pin must be 0-63 (%d)\n", pin) ;
 
   /**/ if (wiringPiMode == WPI_MODE_UNINITIALISED)
     return wiringPiFailure (WPI_FATAL, "wiringPiISR: wiringPi has not been initialised. Unable to continue.\n") ;
@@ -1333,26 +1372,26 @@ int wiringPiISR (int pin, int mode, void (*function)(void))
     sprintf (pinS, "%d", bcmGpioPin) ;
 
     if ((pid = fork ()) < 0)   // Fail
-      return pid ;
+      return wiringPiFailure (WPI_FATAL, "wiringPiISR: fork failed: %s\n", strerror (errno)) ;
 
     if (pid == 0)      // Child, exec
     {
       execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ;
-      return -1 ;      // Failure ...
+      return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ;
     }
     else               // Parent, wait
       wait (NULL) ;
   }
 
-// Now pre-open the /sys/class node - it may already be open if
-//     we are in Sys mode or if we call here twice, if-so, we'll close it.
-
-  if (sysFds [bcmGpioPin] != -1)
-    close (sysFds [bcmGpioPin]) ;
+// Now pre-open the /sys/class node - but it may already be open if
+//     we are in Sys mode...
 
-  sprintf (fName, "/sys/class/gpio/gpio%d/value", bcmGpioPin) ;
-  if ((sysFds [bcmGpioPin] = open (fName, O_RDWR)) < 0)
-    return -1 ;
+  if (sysFds [bcmGpioPin] == -1)
+  {
+    sprintf (fName, "/sys/class/gpio/gpio%d/value", bcmGpioPin) ;
+    if ((sysFds [bcmGpioPin] = open (fName, O_RDWR)) < 0)
+      return wiringPiFailure (WPI_FATAL, "wiringPiISR: unable to open %s: %s\n", fName, strerror (errno)) ;
+  }
 
 // Clear any initial pending interrupt
 
@@ -1441,6 +1480,8 @@ void delayMicrosecondsHard (unsigned int howLong)
 void delayMicroseconds (unsigned int howLong)
 {
   struct timespec sleeper ;
+  unsigned int uSecs = howLong % 1000000 ;
+  unsigned int wSecs = howLong / 1000000 ;
 
   /**/ if (howLong ==   0)
     return ;
@@ -1448,8 +1489,8 @@ void delayMicroseconds (unsigned int howLong)
     delayMicrosecondsHard (howLong) ;
   else
   {
-    sleeper.tv_sec  = 0 ;
-    sleeper.tv_nsec = (long)(howLong * 1000) ;
+    sleeper.tv_sec  = wSecs ;
+    sleeper.tv_nsec = (long)(uSecs * 1000L) ;
     nanosleep (&sleeper, NULL) ;
   }
 }
@@ -1532,7 +1573,7 @@ int wiringPiSetup (void)
 
 // Open the master /dev/memory device
 
-  if ((fd = open ("/dev/mem", O_RDWR | O_SYNC) ) < 0)
+  if ((fd = open ("/dev/mem", O_RDWR | O_SYNC | O_CLOEXEC) ) < 0)
     return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open /dev/mem: %s\n", strerror (errno)) ;
 
 // GPIO: