chiark / gitweb /
More typos, added mcp3004/mcp3008
[wiringPi.git] / gpio / gpio.c
index 326dd2d9558e87c9514e2e18544f263538b12649..1933a694f2566dd581ef0cbdc411a9146395792e 100644 (file)
@@ -2,7 +2,7 @@
  * gpio.c:
  *     Swiss-Army-Knife, Set-UID command-line interface to the Raspberry
  *     Pi's GPIO.
- *     Copyright (c) 2012 Gordon Henderson
+ *     Copyright (c) 2012-2013 Gordon Henderson
  ***********************************************************************
  * This file is part of wiringPi:
  *     https://projects.drogon.net/raspberry-pi/wiringpi/
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <ctype.h>
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
-#include <sys/types.h>
 #include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
 
 #include <wiringPi.h>
+
 #include <gertboard.h>
+#include <piFace.h>
+
+#include "extensions.h"
 
 extern int wiringPiDebug ;
 
@@ -42,22 +48,26 @@ extern int wiringPiDebug ;
 #  define      FALSE   (1==2)
 #endif
 
-#define        VERSION "1.8"
+#define        VERSION         "2.06"
+#define        I2CDETECT       "/usr/sbin/i2cdetect"
 
 static int wpMode ;
 
 char *usage = "Usage: gpio -v\n"
               "       gpio -h\n"
-              "       gpio [-g] <read/write/wb/pwm/mode> ...\n"
+              "       gpio [-g|-1] [-x extension:params] ...\n"
               "       gpio [-p] <read/write/wb> ...\n"
-             "       gpio readall\n"
-             "       gpio unexportall/exports ...\n"
+              "       gpio <read/write/aread/awritewb/pwm/clock/mode> ...\n"
+             "       gpio readall/reset\n"
+             "       gpio unexportall/exports\n"
              "       gpio export/edge/unexport ...\n"
+             "       gpio wfi <pin> <mode>\n"
              "       gpio drive <group> <value>\n"
              "       gpio pwm-bal/pwm-ms \n"
              "       gpio pwmr <range> \n"
              "       gpio pwmc <divider> \n"
              "       gpio load spi/i2c\n"
+             "       gpio i2cd/i2cdetect\n"
              "       gpio gbr <channel>\n"
              "       gpio gbw <channel> <value>" ;     // No trailing newline needed here.
 
@@ -129,7 +139,7 @@ static int moduleLoaded (char *modName)
 
 static void _doLoadUsage (char *argv [])
 {
-  fprintf (stderr, "Usage: %s load <spi/i2c> [bufferSize in KB for spi]\n", argv [0]) ;
+  fprintf (stderr, "Usage: %s load <spi/i2c> [SPI bufferSize in KB | I2C baudrate in Kb/sec]\n", argv [0]) ;
   exit (1) ;
 }
 
@@ -138,12 +148,12 @@ static void doLoad (int argc, char *argv [])
   char *module1, *module2 ;
   char cmd [80] ;
   char *file1, *file2 ;
-  char spiBuf [32] ;
+  char args1 [32], args2 [32] ;
 
   if (argc < 3)
     _doLoadUsage (argv) ;
 
-  spiBuf [0] = 0 ;
+  args1 [0] = args2 [0] = 0 ;
 
   /**/ if (strcasecmp (argv [2], "spi") == 0)
   {
@@ -152,10 +162,9 @@ static void doLoad (int argc, char *argv [])
     file1  = "/dev/spidev0.0" ;
     file2  = "/dev/spidev0.1" ;
     if (argc == 4)
-      sprintf (spiBuf, " bufsize=%d", atoi (argv [3]) * 1024) ;
+      sprintf (args1, " bufsiz=%d", atoi (argv [3]) * 1024) ;
     else if (argc > 4)
       _doLoadUsage (argv) ;
-    
   }
   else if (strcasecmp (argv [2], "i2c") == 0)
   {
@@ -163,19 +172,23 @@ static void doLoad (int argc, char *argv [])
     module2 = "i2c_bcm2708" ;
     file1  = "/dev/i2c-0" ;
     file2  = "/dev/i2c-1" ;
+    if (argc == 4)
+      sprintf (args2, " baudrate=%d", atoi (argv [3]) * 1000) ;
+    else if (argc > 4)
+      _doLoadUsage (argv) ;
   }
   else
     _doLoadUsage (argv) ;
 
   if (!moduleLoaded (module1))
   {
-    sprintf (cmd, "modprobe %s%s", module1, spiBuf) ;
+    sprintf (cmd, "modprobe %s%s", module1, args1) ;
     system (cmd) ;
   }
 
   if (!moduleLoaded (module2))
   {
-    sprintf (cmd, "modprobe %s", module2) ;
+    sprintf (cmd, "modprobe %s%s", module2, args2) ;
     system (cmd) ;
   }
 
@@ -192,6 +205,37 @@ static void doLoad (int argc, char *argv [])
 }
 
 
+/*
+ * doI2Cdetect:
+ *     Run the i2cdetect command with the right runes for this Pi revision
+ *********************************************************************************
+ */
+
+static void doI2Cdetect (int argc, char *argv [])
+{
+  int port = piBoardRev () == 1 ? 0 : 1 ;
+  char command [128] ;
+  struct stat statBuf ;
+
+  if (stat (I2CDETECT, &statBuf) < 0)
+  {
+    fprintf (stderr, "%s: Unable to find i2cdetect command: %s\n", argv [0], strerror (errno)) ;
+    return ;
+  }
+
+  if (!moduleLoaded ("i2c_dev"))
+  {
+    fprintf (stderr, "%s: The I2C kernel module(s) are not loaded.\n", argv [0]) ;
+    return ;
+  }
+
+  sprintf (command, "%s -y %d", I2CDETECT, port) ;
+  if (system (command) < 0)
+    fprintf (stderr, "%s: Unable to run i2cdetect: %s\n", argv [0], strerror (errno)) ;
+
+}
+
+
 /*
  * doReadall:
  *     Read all the GPIO pins
@@ -200,55 +244,51 @@ static void doLoad (int argc, char *argv [])
 
 static char *pinNames [] =
 {
-  "GPIO 0",
-  "GPIO 1",
-  "GPIO 2",
-  "GPIO 3",
-  "GPIO 4",
-  "GPIO 5",
-  "GPIO 6",
-  "GPIO 7",
-  "SDA   ",
-  "SCL   ",
-  "CE0   ",
-  "CE1   ",
-  "MOSI  ",
-  "MISO  ",
-  "SCLK  ",
-  "TxD   ",
-  "RxD   ",
-  "GPIO 8",
-  "GPIO 9",
-  "GPIO10",
-  "GPIO11",
+  "GPIO 0", "GPIO 1", "GPIO 2", "GPIO 3", "GPIO 4", "GPIO 5", "GPIO 6", "GPIO 7",
+  "SDA   ", "SCL   ",
+  "CE0   ", "CE1   ", "MOSI  ", "MISO  ", "SCLK  ",
+  "TxD   ", "RxD   ",
+  "GPIO 8", "GPIO 9", "GPIO10", "GPIO11",
 } ;
 
-static void doReadall (void)
+static char *alts [] =
 {
-  int pin ;
+  "IN  ", "OUT ", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3"
+} ;
 
-  printf ("+----------+------+--------+-------+\n") ;
-  printf ("| wiringPi | GPIO | Name   | Value |\n") ;
-  printf ("+----------+------+--------+-------+\n") ;
+static int wpiToPhys [64] =
+{
+  11, 12, 13, 15, 16, 18, 22,  7,      //  0...7
+   3,  5,                              //  8...9
+  24, 26, 19, 21, 23,                  // 10..14
+   8, 10,                              // 15..16
+   3,  4,  5,  6,                      // 17..20
+             0,0,0,0,0,0,0,0,0,0,0,    // 20..31
+   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    // 32..47
+   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,    // 47..63
+} ;
 
-  for (pin = 0 ; pin < NUM_PINS ; ++pin)
-    printf ("| %6d   | %3d  | %s | %s  |\n",
-       pin, wpiPinToGpio (pin),
-       pinNames [pin], 
-       digitalRead (pin) == HIGH ? "High" : "Low ") ;
+static void doReadall (void)
+{
+  int pin ;
 
-  printf ("+----------+------+--------+-------+\n") ;
+  printf ("+----------+-Rev%d-+------+--------+------+-------+\n", piBoardRev ()) ;
+  printf ("| wiringPi | GPIO | Phys | Name   | Mode | Value |\n") ;
+  printf ("+----------+------+------+--------+------+-------+\n") ;
 
-  if (piBoardRev () == 1)
-    return ;
+  for (pin = 0 ; pin < 64 ; ++pin)     // Crude, but effective
+  {
+    if (wpiPinToGpio (pin) == -1)
+      continue ;
 
-  for (pin = 17 ; pin <= 20 ; ++pin)
-    printf ("| %6d   | %3d  | %s | %s  |\n",
-       pin, wpiPinToGpio (pin),
+    printf ("| %6d   | %3d  | %3d  | %s | %s | %s  |\n",
+       pin, wpiPinToGpio (pin), wpiToPhys [pin],
        pinNames [pin], 
+       alts [getAlt (pin)], 
        digitalRead (pin) == HIGH ? "High" : "Low ") ;
+  }
 
-  printf ("+----------+------+--------+-------+\n") ;
+  printf ("+----------+------+------+--------+------+-------+\n") ;
 }
 
 
@@ -265,9 +305,7 @@ static void doExports (int argc, char *argv [])
   char fName [128] ;
   char buf [16] ;
 
-// Rather crude, but who knows what others are up to...
-
-  for (first = 0, i = 0 ; i < 64 ; ++i)
+  for (first = 0, i = 0 ; i < 64 ; ++i)        // Crude, but effective
   {
 
 // Try to read the direction
@@ -399,6 +437,52 @@ void doExport (int argc, char *argv [])
 }
 
 
+/*
+ * doWfi:
+ *     gpio wfi pin mode
+ *     Wait for Interrupt on a given pin.
+ *     Slight cheat here - it's easier to actually use ISR now (which calls
+ *     gpio to set the pin modes!) then we simply sleep, and expect the thread
+ *     to exit the program. Crude but effective.
+ *********************************************************************************
+ */
+
+static void wfi (void)
+  { exit (0) ; }
+
+void doWfi (int argc, char *argv [])
+{
+  int pin, mode ;
+
+  if (argc != 4)
+  {
+    fprintf (stderr, "Usage: %s wfi pin mode\n", argv [0]) ;
+    exit (1) ;
+  }
+
+  pin  = atoi (argv [2]) ;
+
+  /**/ if (strcasecmp (argv [3], "rising")  == 0) mode = INT_EDGE_RISING ;
+  else if (strcasecmp (argv [3], "falling") == 0) mode = INT_EDGE_FALLING ;
+  else if (strcasecmp (argv [3], "both")    == 0) mode = INT_EDGE_BOTH ;
+  else
+  {
+    fprintf (stderr, "%s: wfi: Invalid mode: %s. Should be rising, falling or both\n", argv [1], argv [3]) ;
+    exit (1) ;
+  }
+
+  if (wiringPiISR (pin, mode, &wfi) < 0)
+  {
+    fprintf (stderr, "%s: wfi: Unable to setup ISR: %s\n", argv [1], strerror (errno)) ;
+    exit (1) ;
+  }
+
+  for (;;)
+    delay (9999) ;
+}
+
+
+
 /*
  * doEdge:
  *     gpio edge pin mode
@@ -512,7 +596,7 @@ void doUnexport (int argc, char *argv [])
  *********************************************************************************
  */
 
-void doUnexportall (int argc, char *argv [])
+void doUnexportall (char *progName)
 {
   FILE *fd ;
   int pin ;
@@ -521,7 +605,7 @@ void doUnexportall (int argc, char *argv [])
   {
     if ((fd = fopen ("/sys/class/gpio/unexport", "w")) == NULL)
     {
-      fprintf (stderr, "%s: Unable to open GPIO export interface\n", argv [0]) ;
+      fprintf (stderr, "%s: Unable to open GPIO export interface\n", progName) ;
       exit (1) ;
     }
     fprintf (fd, "%d\n", pin) ;
@@ -530,6 +614,30 @@ void doUnexportall (int argc, char *argv [])
 }
 
 
+/*
+ * doReset:
+ *     Reset the GPIO pins - as much as we can do
+ *********************************************************************************
+ */
+
+static void doReset (char *progName)
+{
+  int pin ;
+
+  doUnexportall (progName) ;
+
+  for (pin = 0 ; pin < 64 ; ++pin)
+  {
+    if (wpiPinToGpio (pin) == -1)
+      continue ;
+
+    digitalWrite    (pin, LOW) ;
+    pinMode         (pin, INPUT) ;
+    pullUpDnControl (pin, PUD_OFF) ;
+  }
+}
+
+
 /*
  * doMode:
  *     gpio mode pin mode ...
@@ -549,20 +657,18 @@ void doMode (int argc, char *argv [])
 
   pin = atoi (argv [2]) ;
 
-  if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
-    return ;
-
   mode = argv [3] ;
 
-  /**/ if (strcasecmp (mode, "in")   == 0) pinMode         (pin, INPUT) ;
-  else if (strcasecmp (mode, "out")  == 0) pinMode         (pin, OUTPUT) ;
-  else if (strcasecmp (mode, "pwm")  == 0) pinMode         (pin, PWM_OUTPUT) ;
-  else if (strcasecmp (mode, "up")   == 0) pullUpDnControl (pin, PUD_UP) ;
-  else if (strcasecmp (mode, "down") == 0) pullUpDnControl (pin, PUD_DOWN) ;
-  else if (strcasecmp (mode, "tri")  == 0) pullUpDnControl (pin, PUD_OFF) ;
+  /**/ if (strcasecmp (mode, "in")     == 0) pinMode         (pin, INPUT) ;
+  else if (strcasecmp (mode, "out")    == 0) pinMode         (pin, OUTPUT) ;
+  else if (strcasecmp (mode, "pwm")    == 0) pinMode         (pin, PWM_OUTPUT) ;
+  else if (strcasecmp (mode, "clock")  == 0) pinMode         (pin, GPIO_CLOCK) ;
+  else if (strcasecmp (mode, "up")     == 0) pullUpDnControl (pin, PUD_UP) ;
+  else if (strcasecmp (mode, "down")   == 0) pullUpDnControl (pin, PUD_DOWN) ;
+  else if (strcasecmp (mode, "tri")    == 0) pullUpDnControl (pin, PUD_OFF) ;
   else
   {
-    fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/up/down/tri\n", argv [1], mode) ;
+    fprintf (stderr, "%s: Invalid mode: %s. Should be in/out/pwm/clock/up/down/tri\n", argv [1], mode) ;
     exit (1) ;
   }
 }
@@ -616,7 +722,7 @@ static void doGbw (int argc, char *argv [])
 
   if (argc != 4)
   {
-    fprintf (stderr, "Usage: %s gbr <channel> <value>\n", argv [0]) ;
+    fprintf (stderr, "Usage: %s gbw <channel> <value>\n", argv [0]) ;
     exit (1) ;
   }
 
@@ -625,23 +731,23 @@ static void doGbw (int argc, char *argv [])
 
   if ((channel < 0) || (channel > 1))
   {
-    fprintf (stderr, "%s: channel must be 0 or 1\n", argv [0]) ;
+    fprintf (stderr, "%s: gbw: Channel number must be 0 or 1\n", argv [0]) ;
     exit (1) ;
   }
 
   if ((value < 0) || (value > 1023))
   {
-    fprintf (stderr, "%s: value must be from 0 to 255\n", argv [0]) ;
+    fprintf (stderr, "%s: gbw: Value must be from 0 to 255\n", argv [0]) ;
     exit (1) ;
   }
 
-  if (gertboardSPISetup () == -1)
+  if (gertboardAnalogSetup (64) < 0)
   {
     fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
     exit (1) ;
   }
 
-  gertboardAnalogWrite (channel, value) ;
+  analogWrite (64 + channel, value) ;
 }
 
 
@@ -666,21 +772,20 @@ static void doGbr (int argc, char *argv [])
 
   if ((channel < 0) || (channel > 1))
   {
-    fprintf (stderr, "%s: channel must be 0 or 1\n", argv [0]) ;
+    fprintf (stderr, "%s: gbr: Channel number must be 0 or 1\n", argv [0]) ;
     exit (1) ;
   }
 
-  if (gertboardSPISetup () == -1)
+  if (gertboardAnalogSetup (64) < 0)
   {
     fprintf (stderr, "Unable to initialise the Gertboard SPI interface: %s\n", strerror (errno)) ;
     exit (1) ;
   }
 
-  printf ("%d\n",gertboardAnalogRead (channel)) ;
+  printf ("%d\n", analogRead (64 + channel)) ;
 }
 
 
-
 /*
  * doWrite:
  *     gpio write pin value
@@ -699,9 +804,6 @@ static void doWrite (int argc, char *argv [])
 
   pin = atoi (argv [2]) ;
 
-  if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
-    return ;
-
   /**/ if ((strcasecmp (argv [3], "up") == 0) || (strcasecmp (argv [3], "on") == 0))
     val = 1 ;
   else if ((strcasecmp (argv [3], "down") == 0) || (strcasecmp (argv [3], "off") == 0))
@@ -715,6 +817,31 @@ static void doWrite (int argc, char *argv [])
     digitalWrite (pin, HIGH) ;
 }
 
+
+/*
+ * doAwriterite:
+ *     gpio awrite pin value
+ *********************************************************************************
+ */
+
+static void doAwrite (int argc, char *argv [])
+{
+  int pin, val ;
+
+  if (argc != 4)
+  {
+    fprintf (stderr, "Usage: %s awrite pin value\n", argv [0]) ;
+    exit (1) ;
+  }
+
+  pin = atoi (argv [2]) ;
+
+  val = atoi (argv [3]) ;
+
+  analogWrite (pin, val) ;
+}
+
+
 /*
  * doWriteByte:
  *     gpio write value
@@ -754,16 +881,72 @@ void doRead (int argc, char *argv [])
   }
 
   pin = atoi (argv [2]) ;
+  val = digitalRead (pin) ;
 
-  if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
+  printf ("%s\n", val == 0 ? "0" : "1") ;
+}
+
+
+/*
+ * doAread:
+ *     Read an analog pin and return the value
+ *********************************************************************************
+ */
+
+void doAread (int argc, char *argv []) 
+{
+  if (argc != 3)
   {
-    printf ("0\n") ;
-    return ;
+    fprintf (stderr, "Usage: %s aread pin\n", argv [0]) ;
+    exit (1) ;
   }
 
-  val = digitalRead (pin) ;
+  printf ("%d\n", analogRead (atoi (argv [2]))) ;
+}
 
-  printf ("%s\n", val == 0 ? "0" : "1") ;
+
+/*
+ * doToggle:
+ *     Toggle an IO pin
+ *********************************************************************************
+ */
+
+void doToggle (int argc, char *argv [])
+{
+  int pin ;
+
+  if (argc != 3)
+  {
+    fprintf (stderr, "Usage: %s toggle pin\n", argv [0]) ;
+    exit (1) ;
+  }
+
+  pin = atoi (argv [2]) ;
+
+  digitalWrite (pin, !digitalRead (pin)) ;
+}
+
+/*
+ * doClock:
+ *     Output a clock on a pin
+ *********************************************************************************
+ */
+
+void doClock (int argc, char *argv [])
+{
+  int pin, freq ;
+
+  if (argc != 4)
+  {
+    fprintf (stderr, "Usage: %s clock <pin> <freq>\n", argv [0]) ;
+    exit (1) ;
+  }
+
+  pin = atoi (argv [2]) ;
+
+  freq = atoi (argv [3]) ;
+
+  gpioClockSet (pin, freq) ;
 }
 
 
@@ -785,9 +968,6 @@ void doPwm (int argc, char *argv [])
 
   pin = atoi (argv [2]) ;
 
-  if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS)))
-    return ;
-
   val = atoi (argv [3]) ;
 
   pwmWrite (pin, val) ;
@@ -870,16 +1050,34 @@ int main (int argc, char *argv [])
     return 1 ;
   }
 
+// Help
+
   if (strcasecmp (argv [1], "-h") == 0)
   {
     printf ("%s: %s\n", argv [0], usage) ;
     return 0 ;
   }
 
-  if (strcasecmp (argv [1], "-v") == 0)
+// Sort of a special:
+
+  if (strcmp (argv [1], "-R") == 0)
+  {
+    printf ("%d\n", piBoardRev ()) ;
+    return 0 ;
+  }
+
+// Version & Warranty
+
+  if (strcmp (argv [1], "-V") == 0)
+  {
+    printf ("%d\n", piBoardRev ()) ;
+    return 0 ;
+  }
+
+  if (strcmp (argv [1], "-v") == 0)
   {
     printf ("gpio version: %s\n", VERSION) ;
-    printf ("Copyright (c) 2012 Gordon Henderson\n") ;
+    printf ("Copyright (c) 2012-2013 Gordon Henderson\n") ;
     printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
     printf ("For details type: %s -warranty\n", argv [0]) ;
     printf ("\n") ;
@@ -890,7 +1088,7 @@ int main (int argc, char *argv [])
   if (strcasecmp (argv [1], "-warranty") == 0)
   {
     printf ("gpio version: %s\n", VERSION) ;
-    printf ("Copyright (c) 2012 Gordon Henderson\n") ;
+    printf ("Copyright (c) 2012-2013 Gordon Henderson\n") ;
     printf ("\n") ;
     printf ("    This program is free software; you can redistribute it and/or modify\n") ;
     printf ("    it under the terms of the GNU Leser General Public License as published\n") ;
@@ -919,8 +1117,8 @@ int main (int argc, char *argv [])
   /**/ if (strcasecmp (argv [1], "exports"    ) == 0)  { doExports     (argc, argv) ;  return 0 ; }
   else if (strcasecmp (argv [1], "export"     ) == 0)  { doExport      (argc, argv) ;  return 0 ; }
   else if (strcasecmp (argv [1], "edge"       ) == 0)  { doEdge        (argc, argv) ;  return 0 ; }
-  else if (strcasecmp (argv [1], "unexportall") == 0)  { doUnexportall (argc, argv) ;  return 0 ; }
   else if (strcasecmp (argv [1], "unexport"   ) == 0)  { doUnexport    (argc, argv) ;  return 0 ; }
+  else if (strcasecmp (argv [1], "unexportall") == 0)  { doUnexportall (argv [0]) ;    return 0 ; }
 
 // Check for load command:
 
@@ -933,13 +1131,9 @@ int main (int argc, char *argv [])
 
 // Check for -g argument
 
-  if (strcasecmp (argv [1], "-g") == 0)
+  /**/ if (strcasecmp (argv [1], "-g") == 0)
   {
-    if (wiringPiSetupGpio () == -1)
-    {
-      fprintf (stderr, "%s: Unable to initialise GPIO mode.\n", argv [0]) ;
-      exit (1) ;
-    }
+    wiringPiSetupGpio () ;
 
     for (i = 2 ; i < argc ; ++i)
       argv [i - 1] = argv [i] ;
@@ -947,15 +1141,23 @@ int main (int argc, char *argv [])
     wpMode = WPI_MODE_GPIO ;
   }
 
+// Check for -1 argument
+
+  else if (strcasecmp (argv [1], "-1") == 0)
+  {
+    wiringPiSetupPhys () ;
+
+    for (i = 2 ; i < argc ; ++i)
+      argv [i - 1] = argv [i] ;
+    --argc ;
+    wpMode = WPI_MODE_PHYS ;
+  }
+
 // Check for -p argument for PiFace
 
   else if (strcasecmp (argv [1], "-p") == 0)
   {
-    if (wiringPiSetupPiFaceForGpioProg () == -1)
-    {
-      fprintf (stderr, "%s: Unable to initialise PiFace.\n", argv [0]) ;
-      exit (1) ;
-    }
+    piFaceSetup (200) ;
 
     for (i = 2 ; i < argc ; ++i)
       argv [i - 1] = argv [i] ;
@@ -967,37 +1169,65 @@ int main (int argc, char *argv [])
 
   else
   {
-    if (wiringPiSetup () == -1)
-    {
-      fprintf (stderr, "%s: Unable to initialise wiringPi mode\n", argv [0]) ;
-      exit (1) ;
-    }
+    wiringPiSetup () ;
     wpMode = WPI_MODE_PINS ;
   }
 
-// Check for PWM or Pad Drive operations
+// Check for -x argument to load in a new extension
 
-  if (wpMode != WPI_MODE_PIFACE)
+  if (strcasecmp (argv [1], "-x") == 0)
   {
-    if (strcasecmp (argv [1], "pwm-bal") == 0) { doPwmMode  (PWM_MODE_BAL) ;   return 0 ; }
-    if (strcasecmp (argv [1], "pwm-ms")  == 0) { doPwmMode  (PWM_MODE_MS) ;    return 0 ; }
-    if (strcasecmp (argv [1], "pwmr")    == 0) { doPwmRange (argc, argv) ;     return 0 ; }
-    if (strcasecmp (argv [1], "pwmc")    == 0) { doPwmClock (argc, argv) ;     return 0 ; }
-    if (strcasecmp (argv [1], "drive")   == 0) { doPadDrive (argc, argv) ;     return 0 ; }
+    if (argc < 3)
+    {
+      fprintf (stderr, "%s: -x missing extension specification.\n", argv [0]) ;
+      exit (EXIT_FAILURE) ;
+    }
+
+    if (!doExtension (argv [0], argv [2]))     // Prints its own error messages
+      exit (EXIT_FAILURE) ;
+
+    for (i = 3 ; i < argc ; ++i)
+      argv [i - 2] = argv [i] ;
+    argc -= 2 ;
   }
 
-// Check for wiring commands
+  if (argc <= 1)
+  {
+    fprintf (stderr, "%s: no command given\n", argv [0]) ;
+    exit (EXIT_FAILURE) ;
+  }
 
-  /**/ if (strcasecmp (argv [1], "readall" ) == 0) doReadall   () ;
-  else if (strcasecmp (argv [1], "read" )    == 0) doRead      (argc, argv) ;
-  else if (strcasecmp (argv [1], "write")    == 0) doWrite     (argc, argv) ;
-  else if (strcasecmp (argv [1], "wb")       == 0) doWriteByte (argc, argv) ;
-  else if (strcasecmp (argv [1], "pwm"  )    == 0) doPwm       (argc, argv) ;
-  else if (strcasecmp (argv [1], "mode" )    == 0) doMode      (argc, argv) ;
+// Core wiringPi functions
+
+  /**/ if (strcasecmp (argv [1], "mode"   ) == 0) doMode      (argc, argv) ;
+  else if (strcasecmp (argv [1], "read"   ) == 0) doRead      (argc, argv) ;
+  else if (strcasecmp (argv [1], "write"  ) == 0) doWrite     (argc, argv) ;
+  else if (strcasecmp (argv [1], "pwm"    ) == 0) doPwm       (argc, argv) ;
+  else if (strcasecmp (argv [1], "awrite" ) == 0) doAwrite    (argc, argv) ;
+  else if (strcasecmp (argv [1], "aread"  ) == 0) doAread     (argc, argv) ;
+
+// GPIO Nicies
+
+  else if (strcasecmp (argv [1], "toggle" ) == 0) doToggle    (argc, argv) ;
+
+// Pi Specifics
+
+  else if (strcasecmp (argv [1], "pwm-bal"  ) == 0) doPwmMode   (PWM_MODE_BAL) ;
+  else if (strcasecmp (argv [1], "pwm-ms"   ) == 0) doPwmMode   (PWM_MODE_MS) ;
+  else if (strcasecmp (argv [1], "pwmr"     ) == 0) doPwmRange  (argc, argv) ;
+  else if (strcasecmp (argv [1], "pwmc"     ) == 0) doPwmClock  (argc, argv) ;
+  else if (strcasecmp (argv [1], "drive"    ) == 0) doPadDrive  (argc, argv) ;
+  else if (strcasecmp (argv [1], "readall"  ) == 0) doReadall   () ;
+  else if (strcasecmp (argv [1], "i2cdetect") == 0) doI2Cdetect (argc, argv) ;
+  else if (strcasecmp (argv [1], "i2cd"     ) == 0) doI2Cdetect (argc, argv) ;
+  else if (strcasecmp (argv [1], "reset"    ) == 0) doReset     (argv [0]) ;
+  else if (strcasecmp (argv [1], "wb"       ) == 0) doWriteByte (argc, argv) ;
+  else if (strcasecmp (argv [1], "clock"    ) == 0) doClock     (argc, argv) ;
+  else if (strcasecmp (argv [1], "wfi"      ) == 0) doWfi       (argc, argv) ;
   else
   {
     fprintf (stderr, "%s: Unknown command: %s.\n", argv [0], argv [1]) ;
-    exit (1) ;
+    exit (EXIT_FAILURE) ;
   }
   return 0 ;
 }