diff --git a/devLib/Makefile b/devLib/Makefile index 58903a3..87f1e96 100644 --- a/devLib/Makefile +++ b/devLib/Makefile @@ -43,15 +43,12 @@ LIBS = ############################################################################### -SRC = ds1302.c maxdetect.c \ - piNes.c piFace.c \ - lcd128x64.c lcd.c \ - scrollPhat.c \ - piGlow.c +SRC = ds1302.c maxdetect.c piNes.c \ + lcd128x64.c lcd.c OBJ = $(SRC:.c=.o) -HEADERS = ds1302.h lcd128x64.h lcd.h maxdetect.h piFace.h piGlow.h piNes.h scrollPhat.h +HEADERS = ds1302.h lcd128x64.h lcd.h maxdetect.h piNes.h ################################################################################# diff --git a/examples/Makefile b/examples/Makefile index 121d1b5..679b707 100644 --- a/examples/Makefile +++ b/examples/Makefile @@ -40,7 +40,7 @@ LDLIBS = -lwiringPi -lwiringPiDev -lpthread -lm -lcrypt -lrt SRC = \ blink12.c blink12drcs.c blink6drcs.c blink8.c blink8-drcn.c blink.c blink-thread.c \ - buttons2.c buttons.c \ + buttons.c buttons2.c buttons3.c \ clock.c \ delayTest.c \ ds1302.c \ diff --git a/gpio/gpio.c b/gpio/gpio.c index 5db3a12..a5ddad9 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -72,6 +72,7 @@ char *usage = "Usage: gpio -v Show version info\n" " gpio unexportall/exports\n" " gpio export/edge/unexport ...\n" " gpio wfi \n" + " gpio mwfi [,...] \n" " gpio drive \n" " gpio pwm-bal/pwm-ms \n" " gpio pwmr \n" @@ -499,9 +500,12 @@ void doExport (int argc, char *argv[]) * to exit the program. Crude but effective. ********************************************************************************* */ -static void wfi (UNUSED int pin) +static int nInts = 0; +static void wfi (int pin) { - exit (EXIT_SUCCESS); + nInts++; + printf ("wfi: Interrupt on pin %d; nInts=%d\n", pin, nInts); + //exit (EXIT_SUCCESS); } void doWfi (int argc, char *argv[]) @@ -531,8 +535,56 @@ void doWfi (int argc, char *argv[]) exit (1); } - for (;;) - delayMs(9999); + nInts = 0; + printf("%s: Wait for one interrupt...\n", __FUNCTION__); + while (nInts < 1) + { + delayMs(100); + } +} + +void doMWfi (int argc, char *argv[]) +{ + int pinList[MAX_ONBOARD_PINS]; + int n_pins = 0; + int mode; + + if (argc != 4) + { + fprintf (stderr, "Usage: %s mwfi pin[,pin...] mode\n", argv[0]); + exit (1); + } + + // Get list of pins from comma-separated list in argv[2] + char *pt; + pt = strtok (argv[2],","); + while (pt != NULL) + { + pinList[n_pins++] = atoi(pt); + pt = strtok (NULL, ","); + } + + 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 (wiringPiISRmulti (pinList, n_pins, mode, &wfi) < 0) + { + fprintf (stderr, "%s: wfi: Unable to setup ISR: %s\n", argv[1], strerror (errno)); + exit (1); + } + + nInts = 0; + printf("%s: Wait for %d interrupts...\n", __FUNCTION__, n_pins); + while (nInts < n_pins) + { + delayMs(100); + } } @@ -1429,6 +1481,7 @@ int main (int argc, char *argv[]) else if (strcasecmp (argv[1], "rbd" ) == 0) doReadByte (argc, argv, FALSE); else if (strcasecmp (argv[1], "clock" ) == 0) doClock (argc, argv); else if (strcasecmp (argv[1], "wfi" ) == 0) doWfi (argc, argv); + else if (strcasecmp (argv[1], "mwfi" ) == 0) doMWfi (argc, argv); else { fprintf (stderr, "[FATAL] %s: Unknown command: %s.\n", basename(argv[0]), argv[1]); diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index e2a5236..8122b76 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -293,7 +293,6 @@ static uint64_t epochMilli, epochMicro; // Misc static int wiringPiMode = WPI_MODE_UNINITIALISED; -static volatile int pinPass = -1; static pthread_mutex_t pinMutex; // Debugging & Return codes @@ -306,7 +305,7 @@ int wiringPiTryGpioMem = FALSE; // sysFds: // Map a file descriptor from the /sys/class/gpio/gpioX/value -static int sysFds[64] = +static int sysFds[MAX_ONBOARD_PINS] = { -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, @@ -315,7 +314,7 @@ static int sysFds[64] = }; // ISR Data -static void (*isrFunctions[64])(int pin); +static void (*isrFunctions[MAX_ONBOARD_PINS])(int pin); // Doing it the Arduino way with lookup tables... @@ -330,7 +329,7 @@ static int *pinToGpio; // Index: WiringPi pin # // Value @ index: BCM GPIO # // Revision 1, 1.1: -static int pinToGpioR1[64] = +static int pinToGpioR1[MAX_ONBOARD_PINS] = { // From the Original Wiki 17, 18, 21, 22, 23, 24, 25, 4, // GPIO 0 through 7 : wpi 0 - 7 @@ -347,7 +346,7 @@ static int pinToGpioR1[64] = // Index: WiringPi pin # // Value @ index: BCM GPIO # // Revisions 2...: -static int pinToGpioR2[64] = +static int pinToGpioR2[MAX_ONBOARD_PINS] = { // From the Original Wiki 17, 18, 27, 22, 23, 24, 25, 4, // GPIO 0 through 7 : wpi 0 - 7 @@ -372,7 +371,7 @@ static int pinToGpioR2[64] = static int *physToGpio; // Index: Physical pin # // Value @ index: BCM GPIO # -static int physToGpioR1[64] = +static int physToGpioR1[MAX_ONBOARD_PINS] = { -1, // 0 -1, -1, // 1, 2 @@ -396,7 +395,7 @@ static int physToGpioR1[64] = // Index: Physical pin # // Value @ index: BCM GPIO # -static int physToGpioR2[64] = +static int physToGpioR2[MAX_ONBOARD_PINS] = { -1, // 0 -1, -1, // 1, 2 @@ -1272,9 +1271,11 @@ struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins) int pin; struct wiringPiNodeStruct *node; - // Minimum pin base is 64 - if (pinBase < 64) - (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: pinBase of %d is < 64\n", pinBase); + // Minimum pin base is MAX_ONBOARD_PINS + if (pinBase < MAX_ONBOARD_PINS) + { + (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: pinBase of %d is not < %d\n", pinBase, MAX_ONBOARD_PINS); + } // Check all pins in-case there is overlap: for (pin = pinBase; pin < (pinBase + numPins); ++pin) @@ -1322,7 +1323,7 @@ void pinModeAlt (int pin, int mode) setupCheck ("pinModeAlt"); - if ((pin & PI_GPIO_MASK) == 0) // On-board pin + if ((pin & PI_GPIO_MASK) == 0) // On-board pin { if (wiringPiMode == WPI_MODE_PINS) pin = pinToGpio[pin]; @@ -1352,7 +1353,7 @@ void pinMode (int pin, int mode) setupCheck ("pinMode"); - if ((pin & PI_GPIO_MASK) == 0) // On-board pin + if ((pin & PI_GPIO_MASK) == 0) // On-board pin { if (wiringPiMode == WPI_MODE_PINS) pin = pinToGpio[pin]; @@ -1428,7 +1429,7 @@ void pullUpDnControl (int pin, int pud) setupCheck ("pullUpDnControl"); - if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin { if (wiringPiMode == WPI_MODE_PINS) pin = pinToGpio[pin]; @@ -1486,9 +1487,9 @@ int digitalRead (int pin) { char c; struct wiringPiNodeStruct *node = wiringPiNodes; - if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin { - if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode + if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode { if (sysFds[pin] == -1) return LOW; @@ -1542,9 +1543,9 @@ void digitalWrite (int pin, int value) { struct wiringPiNodeStruct *node = wiringPiNodes; - if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin { - if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode + if (wiringPiMode == WPI_MODE_GPIO_SYS) // Sys mode { if (sysFds[pin] != -1) { @@ -1586,7 +1587,7 @@ void pwmWrite (int pin, int value) setupCheck ("pwmWrite"); - if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin + if ((pin & PI_GPIO_MASK) == 0) // On-Board Pin { if (wiringPiMode == WPI_MODE_PINS) pin = pinToGpio[pin]; @@ -1841,15 +1842,12 @@ int waitForInterrupt (int pin, int mS) * fires. ********************************************************************************* */ -static void *interruptHandler (UNUSED void *arg) +static void *interruptHandler (void *arg) { - int myPin; + int myPin = (int)arg; (void)piHiPri (55); // Only effective if we run as root - myPin = pinPass; - pinPass = -1; - for (;;) { if (waitForInterrupt (myPin, -1) > 0) @@ -1865,8 +1863,8 @@ static void *interruptHandler (UNUSED void *arg) /* * wiringPiISR: * Pi Specific. - * Take the details and create an interrupt handler that will do a call- - * back to the user supplied function. + * Take the details and create an interrupt handler that will do a callback + * to the user-supplied function. * Returns 0 on success, -1 on failure (or program exits if !wiringPiReturnCodes) ********************************************************************************* */ @@ -1877,21 +1875,31 @@ int wiringPiISR (int pin, int mode, void (*function)(int)) char fName[64]; char pinS[8]; pid_t pid; - int count, i; + int count; char c; int bcmGpioPin; 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"); + } else if (wiringPiMode == WPI_MODE_PINS) + { bcmGpioPin = pinToGpio[pin]; + } else if (wiringPiMode == WPI_MODE_PHYS) + { bcmGpioPin = physToGpio[pin]; + } else + { bcmGpioPin = pin; + } // Now export the pin and set the right edge // We're going to use the gpio program to do this, so it assumes @@ -1901,16 +1909,24 @@ int wiringPiISR (int pin, int mode, void (*function)(int)) 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", bcmGpioPin); - if ((pid = fork ()) < 0) // Fail + if ((pid = fork ()) < 0) // Fail + { return wiringPiFailure (WPI_FATAL, "wiringPiISR: fork failed: %s\n", strerror (errno)); + } if (pid == 0) // Child, execl (doesn't return if successful) { @@ -1928,7 +1944,9 @@ int wiringPiISR (int pin, int mode, void (*function)(int)) return wiringPiFailure (WPI_FATAL, "wiringPiISR: Can't find gpio program\n"); } else // Parent, wait for child's execl call to finish + { waitpid (pid, NULL, 0); + } } // Parent continues... @@ -1943,24 +1961,158 @@ int wiringPiISR (int pin, int mode, void (*function)(int)) // Clear any initial pending interrupt ioctl (sysFds[bcmGpioPin], FIONREAD, &count); - for (i = 0; i < count; ++i) + for (int i = 0; i < count; ++i) + { read (sysFds[bcmGpioPin], &c, 1); + } // Save caller's callback function - isrFunctions[pin] = function; + isrFunctions[bcmGpioPin] = function; pthread_mutex_lock (&pinMutex); - pinPass = pin; - pthread_create (&threadId, NULL, interruptHandler, NULL); - while (pinPass != -1) - { - delayMs(1); - } + pthread_create (&threadId, NULL, interruptHandler, (void *)bcmGpioPin); pthread_mutex_unlock (&pinMutex); return 0; } +/* + * wiringPiISRmulti: + * Pi Specific. + * Create an interrupt handler that will do a callback to the user-supplied function + * when any of the specified pins changes according to mode. + * Returns 0 on success, -1 on failure (or program exits if !wiringPiReturnCodes) + ********************************************************************************* + */ +int wiringPiISRmulti (int pins[], int n_pins, int mode, void (*function)(int)) +{ + pthread_t threadId; + const char *modeS; + char fName[64]; + char pinS[8]; + pid_t pid; + int count; + char c; + int bcmGpioPins[MAX_ONBOARD_PINS]; + + if (n_pins < 1) + { + return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: Must specify at least one pin.\n"); + } + + // Translate pin list to list of BCM GPIO pins + for (int i=0; i < n_pins; ++i) + { + int pin = pins[i]; + + if ((pin < 0) || (pin > 63)) + { + return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: pin must be 0-63 (%d)\n", pin); + } + + if (wiringPiMode == WPI_MODE_UNINITIALISED) + { + return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: wiringPi has not been initialised. Unable to continue.\n"); + } + else if (wiringPiMode == WPI_MODE_PINS) + { + bcmGpioPins[i] = pinToGpio[pin]; + } + else if (wiringPiMode == WPI_MODE_PHYS) + { + bcmGpioPins[i] = physToGpio[pin]; + } + else + { + bcmGpioPins[i] = pin; + } + } + + // Now export the pins and set the appropriate 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"; + } + + // Export each pin in the list + for (int i=0; i < n_pins; ++i) + { + sprintf (pinS, "%d", bcmGpioPins[i]); + + if ((pid = fork ()) < 0) // Fail + { + return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: fork failed: %s\n", strerror (errno)); + } + + if (pid == 0) // Child, execl (doesn't return if successful) + { + if (access ("/usr/local/bin/gpio", X_OK) == 0) + { + execl ("/usr/local/bin/gpio", "gpio", "edge", pinS, modeS, (char *)NULL); + return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: 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, "wiringPiISRmulti: execl failed: %s\n", strerror (errno)); + } + else + return wiringPiFailure (WPI_FATAL, "wiringPiISRmulti: Can't find gpio program\n"); + } + else // Parent, wait for child's execl call to finish + { + waitpid (pid, NULL, 0); + } + } // end for(pin#) + } // end if (mode != INT_EDGE_SETUP) + + // Parent continues... + + for (int i=0; i < n_pins; ++i) + { + int bcmGpioPin = bcmGpioPins[i]; + + // Now pre-open the /sys/class node - but it may already be open if + // we are in Sys mode... + 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, "wiringPiISRmulti: unable to open %s: %s\n", fName, strerror (errno)); + } + + // Clear any initial pending interrupt + ioctl (sysFds[bcmGpioPin], FIONREAD, &count); + for (int i = 0; i < count; ++i) + { + read (sysFds[bcmGpioPin], &c, 1); + } + + // Save caller's callback function + isrFunctions[bcmGpioPin] = function; + + // Create a separate + pthread_mutex_lock (&pinMutex); + pthread_create (&threadId, NULL, interruptHandler, (void *)bcmGpioPin); + pthread_mutex_unlock (&pinMutex); + } // end for(pin#) + + return 0; +} /* * initialiseEpoch: @@ -2127,6 +2279,8 @@ int wiringPiSetup (void) wiringPiSetuped = TRUE; + // ------------------------------------------------------ + if (getenv (ENV_DEBUG) != NULL) { wiringPiDebug = TRUE; @@ -2142,6 +2296,7 @@ int wiringPiSetup (void) printf ("wiringPi: wiringPiSetup called\n"); } + // ------------------------------------------------------ // Get the board ID information. We're not really using the information here, // but it will give us information like the GPIO layout scheme (2 variants // on the older 26-pin Pi's) and the GPIO peripheral base address. @@ -2153,9 +2308,15 @@ int wiringPiSetup (void) if ((model == PI_MODEL_CM1) || (model == PI_MODEL_CM3) || (model == PI_MODEL_CM3P)) - wiringPiMode = WPI_MODE_GPIO; // Virtual pin numbers 0 through 16 + { + // Compute modules don't use WiringPi pin mode (virtual pins) + wiringPiMode = WPI_MODE_GPIO; // Broadcom GPIO pin numbers + } else - wiringPiMode = WPI_MODE_PINS; // Broadcom GPIO pin numbers + { + // WiringPi pin mode + wiringPiMode = WPI_MODE_PINS; // Virtual pin numbers 0 through 16 + } if (piGpioLayout() == 1) // A, B, Rev 1, 1.1 (Oldest boards) { @@ -2168,14 +2329,19 @@ int wiringPiSetup (void) physToGpio = physToGpioR2; } - // ... - + // BCM2835: Raspberry Pi 1 Models A, A+, B, B+, the Raspberry Pi Zero, the Raspberry Pi Zero W, and the Raspberry Pi Compute Module 1 + // BCM2836: Raspberry Pi 2 Model B (essentially identical to BCM2835) + // BCM2837: Raspberry Pi 3 Model B, later models of the Raspberry Pi 2 Model B, and the Raspberry Pi Compute Module 3 + // (essentially identical to BCM2836) + // BCM2837B0: Raspberry Pi 3 Models A+, B+, and the Raspberry Pi Compute Module 3+ (essentially identical to BCM2837) + // RP3A0 (BCM2710A1): Raspberry Pi Zero 2 W + // BCM2710A1 = silicon die packaged inside the Broadcom BCM2837 chip which is used on the Raspberry Pi 3 switch (model) { - case PI_MODEL_A: case PI_MODEL_B: - case PI_MODEL_AP: case PI_MODEL_BP: - case PI_ALPHA: case PI_MODEL_CM1: + case PI_MODEL_A: case PI_MODEL_AP: + case PI_MODEL_B: case PI_MODEL_BP: case PI_MODEL_ZERO: case PI_MODEL_ZERO_W: + case PI_MODEL_CM1: case PI_ALPHA: piGpioBase = GPIO_PERI_BASE_OLD; piGpioPupOffset = GPPUD; break; @@ -2183,16 +2349,19 @@ int wiringPiSetup (void) case PI_MODEL_4B: case PI_MODEL_400: case PI_MODEL_CM4: + // BCM2711: Raspberry Pi 4 Model B, the Raspberry Pi 400, and the Raspberry Pi Compute Module 4 piGpioBase = GPIO_PERI_BASE_2711; piGpioPupOffset = GPPUPPDN0; break; default: + // PI_MODEL_2B PI_MODEL_3AP PI_MODEL_3B PI_MODEL_3BP PI_MODEL_CM3P PI_MODEL_CM3 piGpioBase = GPIO_PERI_BASE_2835; piGpioPupOffset = GPPUD; break; } + // ------------------------------------------------------ // Open the master /dev/ memory control device // Device strategy: December 2016: // Try /dev/mem. If that fails, then @@ -2246,6 +2415,7 @@ int wiringPiSetup (void) if (timer == MAP_FAILED) return wiringPiFailure (WPI_NON_FATAL, "wiringPiSetup: mmap (TIMER) failed: %s\n", strerror (errno)); + // ------------------------------------------------------ // Set the timer to free-running, 1MHz. // 0xF9 is 249, the timer divide is base clock / (divide+1) // so base clock is 250MHz / 250 = 1MHz. @@ -2253,6 +2423,7 @@ int wiringPiSetup (void) *(timer + TIMER_PRE_DIV) = 0x00000F9; timerIrqRaw = timer + TIMER_IRQ_RAW; + // ------------------------------------------------------ // Export the base addresses for any external software that might need them _wiringPiGpio = gpio; _wiringPiPwm = pwm; @@ -2260,6 +2431,8 @@ int wiringPiSetup (void) _wiringPiPads = pads; _wiringPiTimer = timer; + // ------------------------------------------------------ + initialiseEpoch (); return 0; @@ -2349,7 +2522,7 @@ int wiringPiSetupSys (void) // Open and scan the directory, looking for exported GPIOs, and pre-open // the 'value' interface to speed things up for later - for (pin = 0; pin < 64; ++pin) + for (pin = 0; pin < MAX_ONBOARD_PINS; ++pin) { sprintf (fName, "/sys/class/gpio/gpio%d/value", pin); sysFds[pin] = open (fName, O_RDWR); diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 1b0986f..7eff836 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -37,9 +37,10 @@ #define UNUSED __attribute__((unused)) // Mask for the bottom 64 pins which belong to the Raspberry Pi -// The others are available for the other devices +// The others are available for the other devices // @TODO Replace these checks with a check for (pin < 64) #define PI_GPIO_MASK (0xFFFFFFC0) +#define MAX_ONBOARD_PINS 64 // wiringPi modes @@ -194,6 +195,7 @@ extern volatile unsigned int *_wiringPiPads; extern volatile unsigned int *_wiringPiTimer; extern volatile unsigned int *_wiringPiTimerIrqRaw; +// ---------------------------------------------------------------------------- // Function prototypes // c++ wrappers thanks to a comment by Nick Lott @@ -202,11 +204,13 @@ extern volatile unsigned int *_wiringPiTimerIrqRaw; extern "C" { #endif -// Data +// ---------------------------------------------------------------------------- // Internal extern int wiringPiFailure (int fatal, const char *message, ...); +// ---------------------------------------------------------------------------- + // Core wiringPi functions extern struct wiringPiNodeStruct *wiringPiFindNode (int pin); extern struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins); @@ -233,7 +237,7 @@ extern int digitalRead (int pin); extern void digitalWrite (int pin, int value); // Analog read/write is only for an external hardware module, -// therefore pin must be >= 64 +// therefore pin must be >= MAX_ONBOARD_PINS extern int analogRead (int pin); extern void analogWrite (int pin, int value); @@ -268,10 +272,24 @@ extern unsigned int digitalReadByte2(void); extern void digitalWriteByte (int value); extern void digitalWriteByte2 (int value); +// ---------------------------------------------------------------------------- // Interrupts (Also Pi hardware specific) -extern int waitForInterrupt (int pin, int mS); // Must be in SYS mode (wiringPiSetupSys was called for setup) -extern int wiringPiISR (int pin, int mode, void (*function)(int)); // Uses SYS mode, and also waitForInterrupt +// Set up for a callback to be called when the specified pin changes according to mode. +// mode = INT_EDGE_SETUP, INT_EDGE_FALLING, INT_EDGE_RISING, INT_EDGE_BOTH +// Uses SYS mode, and also waitForInterrupt +extern int wiringPiISR (int pin, int mode, void (*function)(int)); + +// Same as wiringPiISR above, but takes a list of pins to wait for. +// Note that the mode applies to all the specified pins. +extern int wiringPiISRmulti (int pins[], int n_pins, int mode, void (*function)(int)); + +// Internal-only (unless you know how to set up /sys/class/gpio) +// Wait for "interrupt" on a GPIO pin. +// Must be in SYS mode (wiringPiSetupSys was called for setup) +extern int waitForInterrupt (int pin, int mS); + +// ---------------------------------------------------------------------------- // Threads extern int piThreadCreate (void *(*fn)(void *)); extern void piLock (int key); @@ -280,6 +298,8 @@ extern void piUnlock (int key); // Scheduling priority extern int piHiPri (const int pri); +// ---------------------------------------------------------------------------- + extern void delay (unsigned int milliseconds); extern void delayMicroseconds (unsigned int microseconds); // Please use these for code that's easier to comprehend: