chiark / gitweb /
Updated mostly to the gpio readall command to support the Raspberry Pi B+
[wiringPi.git] / wiringPi / wiringPi.c
index ba61d9fab64efa3e3593c2c9b00b7ff67907096e..1e1cfe4fc9575d996678f7479da13851e67fe2e4 100644 (file)
@@ -70,6 +70,9 @@
 #include <sys/wait.h>
 #include <sys/ioctl.h>
 
+#include "softPwm.h"
+#include "softTone.h"
+
 #include "wiringPi.h"
 
 #ifndef        TRUE
@@ -118,7 +121,6 @@ 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
@@ -232,14 +234,16 @@ static void (*isrFunctions [64])(void) ;
 
 // pinToGpio:
 //     Take a Wiring pin (0 through X) and re-map it to the BCM_GPIO pin
-//     Cope for 2 different board revisions here.
+//     Cope for 3 different board revisions here.
 
 static int *pinToGpio ;
 
+// Revision 1, 1.1:
+
 static int pinToGpioR1 [64] =
 {
   17, 18, 21, 22, 23, 24, 25, 4,       // From the Original Wiki - GPIO 0 through 7:   wpi  0 -  7
-   0,  1,                              // I2C  - SDA0, SCL0                            wpi  8 -  9
+   0,  1,                              // I2C  - SDA1, SCL1                            wpi  8 -  9
    8,  7,                              // SPI  - CE1, CE0                              wpi 10 - 11
   10,  9, 11,                          // SPI  - MOSI, MISO, SCLK                      wpi 12 - 14
   14, 15,                              // UART - Tx, Rx                                wpi 15 - 16
@@ -251,6 +255,8 @@ static int pinToGpioR1 [64] =
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,      // ... 63
 } ;
 
+// Revision 2:
+
 static int pinToGpioR2 [64] =
 {
   17, 18, 27, 22, 23, 24, 25, 4,       // From the Original Wiki - GPIO 0 through 7:   wpi  0 -  7
@@ -258,11 +264,13 @@ static int pinToGpioR2 [64] =
    8,  7,                              // SPI  - CE1, CE0                              wpi 10 - 11
   10,  9, 11,                          // SPI  - MOSI, MISO, SCLK                      wpi 12 - 14
   14, 15,                              // UART - Tx, Rx                                wpi 15 - 16
-  28, 29, 30, 31,                      // New GPIOs 8 though 11                        wpi 17 - 20
+  28, 29, 30, 31,                      // Rev 2: New GPIOs 8 though 11                 wpi 17 - 20
+   5,  6, 13, 19, 26,                  // B+                                           wpi 21, 22, 23, 24, 25
+  12, 16, 20, 21,                      // B+                                           wpi 26, 27, 28, 29
+   0,  1,                              // B+                                           wpi 30, 31
 
 // Padding:
 
-                      -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,      // ... 31
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,      // ... 47
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,      // ... 63
 } ;
@@ -271,6 +279,7 @@ static int pinToGpioR2 [64] =
 // physToGpio:
 //     Take a physical pin (1 through 26) and re-map it to the BCM_GPIO pin
 //     Cope for 2 different board revisions here.
+//     Also add in the P5 connector, so the P5 pins are 3,4,5,6, so 53,54,55,56
 
 static int *physToGpio ;
 
@@ -291,8 +300,6 @@ static int physToGpioR1 [64] =
   11,  8,
   -1,  7,      // 25, 26
 
-// Padding:
-
                                               -1, -1, -1, -1, -1,      // ... 31
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,      // ... 47
   -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,      // ... 63
@@ -315,13 +322,23 @@ static int physToGpioR2 [64] =
   11,  8,
   -1,  7,      // 25, 26
 
-// Padding:
+// B+
 
-                                              -1, -1, -1, -1, -1,      // ... 31
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,      // ... 47
-  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,      // ... 63
-} ;
+   0,  1,
+   5, -1,
+   6, 12,
+  13, -1,
+  19, 16,
+  26, 20,
+  -1, 21,
+
+// the P5 connector on the Rev 2 boards:
 
+                           -1, -1, -1, -1, -1, -1, -1,                 // ... 47
+  -1, -1, -1, -1, -1,                                                  // ... 52
+  28, 29, 30, 31,                                                      // ... 53, 54, 55, 56 - P5
+  -1, -1, -1, -1, -1, -1, -1,                                          // ... 63
+} ;
 
 // gpioToGPFSEL:
 //     Map a BCM_GPIO pin to it's Function Selection
@@ -392,7 +409,7 @@ static uint8_t gpioToEDS [] =
 } ;
 
 // gpioToREN
-//     (Word) offset to the Rising edgde ENable register
+//     (Word) offset to the Rising edge ENable register
 
 static uint8_t gpioToREN [] =
 {
@@ -546,22 +563,31 @@ int wiringPiFailure (int fatal, const char *message, ...)
  *
  *     Much confusion here )-:
  *     Seems there are some boards with 0000 in them (mistake in manufacture)
- *     and some board with 0005 in them (another mistake in manufacture?)
  *     So the distinction between boards that I can see is:
  *     0000 - Error
- *     0001 - Not used
- *     0002 - Rev 1
- *     0003 - Rev 1
- *     0004 - Rev 2 (Early reports?
- *     0005 - Rev 2 (but error?)
- *     0006 - Rev 2
- *     0008 - Rev 2 - Model A
- *     000e - Rev 2 + 512MB
- *     000f - Rev 2 + 512MB
+ *     0001 - Not used (Compute - default to Rev 2)
+ *     0002 - Model B, Rev 1, 256MB
+ *     0003 - Model B, Rev 1.1, 256MB, Fuses/D14 removed.
+ *     0004 - Model B, Rev 2, 256MB, Sony
+ *     0005 - Model B, Rev 2, 256MB, Qisda
+ *     0006 - Model B, Rev 2, 256MB, Egoman
+ *     0007 - Model A, Rev 2, 256MB, Egoman
+ *     0008 - Model A, Rev 2, 256MB, Sony
+ *     0009 - Model A, Rev 2, 256MB, Qisda
+ *     000d - Model B, Rev 2, 512MB, Egoman
+ *     000e - Model B, Rev 2, 512MB, Sony
+ *     000f - Model B, Rev 2, 512MB, Qisda
+ *     0010 - Model B+        512MB, Sony
+ *     0011 - Pi compute Module
  *
  *     A small thorn is the olde style overvolting - that will add in
  *             1000000
  *
+ *     The Pi compute module has an revision of 0011 - since we only check the
+ *     last digit, then it's 1, therefore it'll default to not 2 or 3 for a
+ *     Rev 1, so will appear as a Rev 2. This is fine for the most part, but
+ *     we'll properly detect the Compute Module later and adjust accordingly.
+ *
  *********************************************************************************
  */
 
@@ -633,6 +659,92 @@ int piBoardRev (void)
 }
 
 
+/*
+ * piBoardId:
+ *     Do more digging into the board revision string as above, but return
+ *     as much details as we can.
+ *********************************************************************************
+ */
+
+const char *piModelNames [] =
+{
+  "Model A",
+  "Model B",
+  "Model B+",
+  "Compute Module",
+} ;
+
+const char *piRevisionNames[] =
+{
+  "1",
+  "1.1",
+  "2",
+  "1.2",
+} ;
+
+void piBoardId (int *model, int *rev, int *mem, char **maker)
+{
+  FILE *cpuFd ;
+  char line [120] ;
+  char *c ;
+
+  piBoardRev () ;      // Call this first to make sure all's OK. Don't care about the result.
+
+  if ((cpuFd = fopen ("/proc/cpuinfo", "r")) == NULL)
+    piBoardRevOops ("Unable to open /proc/cpuinfo") ;
+
+  while (fgets (line, 120, cpuFd) != NULL)
+    if (strncmp (line, "Revision", 8) == 0)
+      break ;
+
+  fclose (cpuFd) ;
+
+  if (strncmp (line, "Revision", 8) != 0)
+    piBoardRevOops ("No \"Revision\" line") ;
+
+// Chomp trailing CR/NL
+
+  for (c = &line [strlen (line) - 1] ; (*c == '\n') || (*c == '\r') ; --c)
+    *c = 0 ;
+  
+  if (wiringPiDebug)
+    printf ("piboardId: Revision string: %s\n", line) ;
+
+// Scan to first digit
+
+  for (c = line ; *c ; ++c)
+    if (isdigit (*c))
+      break ;
+
+// Make sure its long enough
+
+  if (strlen (c) < 4)
+    piBoardRevOops ("Bogus \"Revision\" line") ;
+  
+// Extract last 4 characters:
+
+  c = c + strlen (c) - 4 ;
+
+// Fill out the replys as appropriate
+
+  /**/ if (strcmp (c, "0002") == 0) { *model = 1 ; *rev = 0 ; *mem = 256 ; *maker = "China"  ; }
+  else if (strcmp (c, "0003") == 0) { *model = 1 ; *rev = 1 ; *mem = 256 ; *maker = "China"  ; }
+  else if (strcmp (c, "0004") == 0) { *model = 1 ; *rev = 2 ; *mem = 256 ; *maker = "Sony"   ; }
+  else if (strcmp (c, "0005") == 0) { *model = 1 ; *rev = 2 ; *mem = 256 ; *maker = "Qisda"  ; }
+  else if (strcmp (c, "0006") == 0) { *model = 1 ; *rev = 2 ; *mem = 256 ; *maker = "Egoman" ; }
+  else if (strcmp (c, "0007") == 0) { *model = 0 ; *rev = 2 ; *mem = 256 ; *maker = "Egoman" ; }
+  else if (strcmp (c, "0008") == 0) { *model = 0 ; *rev = 2 ; *mem = 256 ; *maker = "Sony"   ; }
+  else if (strcmp (c, "0009") == 0) { *model = 1 ; *rev = 2 ; *mem = 256 ; *maker = "Qisda"  ; }
+  else if (strcmp (c, "000d") == 0) { *model = 1 ; *rev = 2 ; *mem = 512 ; *maker = "Egoman" ; }
+  else if (strcmp (c, "000e") == 0) { *model = 1 ; *rev = 2 ; *mem = 512 ; *maker = "Sony"   ; }
+  else if (strcmp (c, "000f") == 0) { *model = 1 ; *rev = 2 ; *mem = 512 ; *maker = "Egoman" ; }
+  else if (strcmp (c, "0010") == 0) { *model = 2 ; *rev = 3 ; *mem = 512 ; *maker = "Sony"   ; }
+  else if (strcmp (c, "0011") == 0) { *model = 3 ; *rev = 1 ; *mem = 512 ; *maker = "Sony"   ; }
+  else                              { *model = 0 ; *rev = 0 ; *mem =   0 ; *maker = "Unkn"   ; }
+}
+
+
 /*
  * wpiPinToGpio:
  *     Translate a wiringPi Pin number to native GPIO pin number.
@@ -925,6 +1037,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:
@@ -936,6 +1074,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
   {
@@ -946,6 +1085,9 @@ void pinMode (int pin, int mode)
     else if (wiringPiMode != WPI_MODE_GPIO)
       return ;
 
+    softPwmStop  (origPin) ;
+    softToneStop (origPin) ;
+
     fSel    = gpioToGPFSEL [pin] ;
     shift   = gpioToShift  [pin] ;
 
@@ -953,9 +1095,18 @@ 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 == SOFT_TONE_OUTPUT)
+      softToneCreate (origPin) ;
+    else if (mode == PWM_TONE_OUTPUT)
+    {
+      pinMode (origPin, PWM_OUTPUT) ;  // Call myself to enable PWM mode
+      pwmSetMode (PWM_MODE_MS) ;
+    }
     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
@@ -965,7 +1116,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)
     {
@@ -1178,6 +1329,28 @@ void analogWrite (int pin, int value)
 }
 
 
+/*
+ * pwmToneWrite:
+ *     Pi Specific.
+ *      Output the given frequency on the Pi's PWM pin
+ *********************************************************************************
+ */
+
+void pwmToneWrite (int pin, int freq)
+{
+  int range ;
+
+  if (freq == 0)
+    pwmWrite (pin, 0) ;             // Off
+  else
+  {
+    range = 600000 / freq ;
+    pwmSetRange (range) ;
+    pwmWrite    (pin, freq / 2) ;
+  }
+}
+
+
 
 /*
  * digitalWriteByte:
@@ -1344,8 +1517,18 @@ int wiringPiISR (int pin, int mode, void (*function)(void))
 
     if (pid == 0)      // Child, exec
     {
-      execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ;
-      return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ;
+      /**/ if (access ("/usr/local/bin/gpio", X_OK) == 0)
+      {
+       execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ;
+       return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ;
+      }
+      else if (access ("/usr/bin/gpio", X_OK) == 0)
+      {
+       execl ("/usr/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL) ;
+       return wiringPiFailure (WPI_FATAL, "wiringPiISR: execl failed: %s\n", strerror (errno)) ;
+      }
+      else
+       return wiringPiFailure (WPI_FATAL, "wiringPiISR: Can't find gpio program\n") ;
     }
     else               // Parent, wait
       wait (NULL) ;
@@ -1506,13 +1689,17 @@ unsigned int micros (void)
  *
  * Default setup: Initialises the system into wiringPi Pin mode and uses the
  *     memory mapped hardware directly.
+ *
+ * Changed now to revert to "gpio" mode if we're running on a Compute Module.
  *********************************************************************************
  */
 
 int wiringPiSetup (void)
 {
-  int      fd ;
-  int      boardRev ;
+  int   fd ;
+  int   boardRev ;
+  int   model, rev, mem ;
+  char *maker ;
 
   if (getenv (ENV_DEBUG) != NULL)
     wiringPiDebug = TRUE ;
@@ -1528,12 +1715,12 @@ int wiringPiSetup (void)
 
   boardRev = piBoardRev () ;
 
-  if (boardRev == 1)
+  /**/ if (boardRev == 1)      // A, B, Rev 1, 1.1
   {
      pinToGpio =  pinToGpioR1 ;
     physToGpio = physToGpioR1 ;
   }
-  else
+  else                                 // A, B, Rev 2, B+, CM
   {
      pinToGpio =  pinToGpioR2 ;
     physToGpio = physToGpioR2 ;
@@ -1586,7 +1773,13 @@ int wiringPiSetup (void)
 
   initialiseEpoch () ;
 
-  wiringPiMode = WPI_MODE_PINS ;
+// If we're running on a compute module, then wiringPi pin numbers don't really many anything...
+
+  piBoardId (&model, &rev, &mem, &maker) ;
+  if (model == PI_MODEL_CM)
+    wiringPiMode = WPI_MODE_GPIO ;
+  else
+    wiringPiMode = WPI_MODE_PINS ;
 
   return 0 ;
 }