X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=gpio%2Fgpio.c;h=8e17ae0f7169333f3128d051dc1c842558f81e6f;hb=da38443cb257a3bbbe4ad7f54ee3f569710a2fe7;hp=e71e432f310ac06ff9c5479621fc6c5948795e22;hpb=98bcb20d9391ebde24f9eb1244f0d238fb1a1dab;p=wiringPi.git diff --git a/gpio/gpio.c b/gpio/gpio.c index e71e432..8e17ae0 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -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/ @@ -26,14 +26,20 @@ #include #include #include +#include #include #include #include -#include #include +#include +#include #include + #include +#include + +#include "extensions.h" extern int wiringPiDebug ; @@ -42,22 +48,26 @@ extern int wiringPiDebug ; # define FALSE (1==2) #endif -#define VERSION "1.12" +#define VERSION "2.02" +#define I2CDETECT "/usr/sbin/i2cdetect" static int wpMode ; char *usage = "Usage: gpio -v\n" " gpio -h\n" - " gpio [-g] ...\n" + " gpio [-g|-1] [-x extension:params] ...\n" " gpio [-p] ...\n" - " gpio readall\n" - " gpio unexportall/exports ...\n" + " gpio ...\n" + " gpio readall/reset\n" + " gpio unexportall/exports\n" " gpio export/edge/unexport ...\n" + " gpio wfi \n" " gpio drive \n" " gpio pwm-bal/pwm-ms \n" " gpio pwmr \n" " gpio pwmc \n" " gpio load spi/i2c\n" + " gpio i2cd/i2cdetect\n" " gpio gbr \n" " gpio gbw " ; // No trailing newline needed here. @@ -195,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 @@ -215,27 +256,39 @@ static char *alts [] = "IN ", "OUT ", "ALT5", "ALT4", "ALT0", "ALT1", "ALT2", "ALT3" } ; +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 +} ; + static void doReadall (void) { int pin ; - printf ("+----------+------+--------+------+-------+\n") ; - printf ("| wiringPi | GPIO | Name | Mode | Value |\n") ; - printf ("+----------+------+--------+------+-------+\n") ; + printf ("+----------+-Rev%d-+------+--------+------+-------+\n", piBoardRev ()) ; + printf ("| wiringPi | GPIO | Phys | Name | Mode | Value |\n") ; + printf ("+----------+------+------+--------+------+-------+\n") ; - for (pin = 0 ; pin < 64 ; ++pin) + for (pin = 0 ; pin < 64 ; ++pin) // Crude, but effective { if (wpiPinToGpio (pin) == -1) continue ; - printf ("| %6d | %3d | %s | %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") ; } @@ -252,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 @@ -386,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 @@ -499,7 +596,7 @@ void doUnexport (int argc, char *argv []) ********************************************************************************* */ -void doUnexportall (int argc, char *argv []) +void doUnexportall (char *progName) { FILE *fd ; int pin ; @@ -508,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) ; @@ -517,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 ... @@ -536,9 +657,6 @@ 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) ; @@ -604,7 +722,7 @@ static void doGbw (int argc, char *argv []) if (argc != 4) { - fprintf (stderr, "Usage: %s gbr \n", argv [0]) ; + fprintf (stderr, "Usage: %s gbw \n", argv [0]) ; exit (1) ; } @@ -613,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) ; } @@ -654,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 @@ -687,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)) @@ -703,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 @@ -742,19 +881,57 @@ void doRead (int argc, char *argv []) } pin = atoi (argv [2]) ; + val = digitalRead (pin) ; + + printf ("%s\n", val == 0 ? "0" : "1") ; +} + + +/* + * doAread: + * Read an analog pin and return the value + ********************************************************************************* + */ + +void doAread (int argc, char *argv []) +{ + int pin, val ; - if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS))) + if (argc != 3) { - printf ("0\n") ; - return ; + fprintf (stderr, "Usage: %s aread pin\n", argv [0]) ; + exit (1) ; } - val = digitalRead (pin) ; + pin = atoi (argv [2]) ; + + val = analogRead (pin) ; 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 @@ -773,9 +950,6 @@ void doClock (int argc, char *argv []) pin = atoi (argv [2]) ; - if ((wpMode == WPI_MODE_PINS) && ((pin < 0) || (pin >= NUM_PINS))) - return ; - freq = atoi (argv [3]) ; gpioClockSet (pin, freq) ; @@ -800,9 +974,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) ; @@ -885,16 +1056,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") ; @@ -905,7 +1094,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") ; @@ -934,8 +1123,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: @@ -948,13 +1137,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] ; @@ -962,15 +1147,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] ; @@ -982,38 +1175,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], "clock") == 0) doClock (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 ; }