Merge pull request #417 from WiringPi/develop

WiringPi 3.18
This commit is contained in:
mstroh
2026-02-08 21:32:04 +01:00
committed by GitHub
65 changed files with 1233 additions and 397 deletions

View File

@@ -1 +1 @@
3.16 3.18

View File

@@ -27,16 +27,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdbool.h>
#include <wiringPi.h> #include <wiringPi.h>
#include "lcd.h" #include "lcd.h"
#ifndef TRUE
# define TRUE (1==1)
# define FALSE (1==2)
#endif
// HD44780U Commands // HD44780U Commands
#define LCD_CLEAR 0x01 #define LCD_CLEAR 0x01
@@ -483,9 +479,9 @@ int lcdInit (const int rows, const int cols, const int bits,
// Rest of the initialisation sequence // Rest of the initialisation sequence
lcdDisplay (lcdFd, TRUE) ; lcdDisplay (lcdFd, true) ;
lcdCursor (lcdFd, FALSE) ; lcdCursor (lcdFd, false) ;
lcdCursorBlink (lcdFd, FALSE) ; lcdCursorBlink (lcdFd, false) ;
lcdClear (lcdFd) ; lcdClear (lcdFd) ;
putCommand (lcd, LCD_ENTRY | LCD_ENTRY_ID) ; putCommand (lcd, LCD_ENTRY | LCD_ENTRY_ID) ;

View File

@@ -24,6 +24,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
//#include <stdlib.h> //#include <stdlib.h>
//#include <unistd.h> //#include <unistd.h>
@@ -31,11 +32,6 @@
#include "maxdetect.h" #include "maxdetect.h"
#ifndef TRUE
# define TRUE (1==1)
# define FALSE (1==2)
#endif
/* /*
* maxDetectLowHighWait: * maxDetectLowHighWait:
@@ -58,7 +54,7 @@ static int maxDetectLowHighWait (const int pin)
{ {
gettimeofday (&now, NULL) ; gettimeofday (&now, NULL) ;
if (timercmp (&now, &timeUp, >)) if (timercmp (&now, &timeUp, >))
return FALSE ; return false ;
} }
// Wait for it to go HIGH // Wait for it to go HIGH
@@ -72,10 +68,10 @@ static int maxDetectLowHighWait (const int pin)
{ {
gettimeofday (&now, NULL) ; gettimeofday (&now, NULL) ;
if (timercmp (&now, &timeUp, >)) if (timercmp (&now, &timeUp, >))
return FALSE ; return false ;
} }
return TRUE ; return true ;
} }
@@ -110,7 +106,7 @@ static unsigned int maxDetectClockByte (const int pin)
/* /*
* maxDetectRead: * maxDetectRead:
* Read in and return the 4 data bytes from the MaxDetect sensor. * Read in and return the 4 data bytes from the MaxDetect sensor.
* Return TRUE/FALSE depending on the checksum validity * Return true/false depending on the checksum validity
********************************************************************************* *********************************************************************************
*/ */
@@ -136,7 +132,7 @@ int maxDetectRead (const int pin, unsigned char buffer [4])
// Now wait for sensor to pull pin low // Now wait for sensor to pull pin low
if (!maxDetectLowHighWait (pin)) if (!maxDetectLowHighWait (pin))
return FALSE ; return false ;
// and read in 5 bytes (40 bits) // and read in 5 bytes (40 bits)
@@ -165,7 +161,7 @@ int maxDetectRead (const int pin, unsigned char buffer [4])
// reading is probably bogus. // reading is probably bogus.
if ((took.tv_sec != 0) || (took.tv_usec > 16000)) if ((took.tv_sec != 0) || (took.tv_usec > 16000))
return FALSE ; return false ;
return checksum == localBuf [4] ; return checksum == localBuf [4] ;
} }
@@ -196,7 +192,7 @@ int readRHT03 (const int pin, int *temp, int *rh)
{ {
*rh = lastRh ; *rh = lastRh ;
*temp = lastTemp ; *temp = lastTemp ;
return TRUE ; return true ;
} }
// Set timeout for next read // Set timeout for next read
@@ -214,7 +210,7 @@ int readRHT03 (const int pin, int *temp, int *rh)
result = maxDetectRead (pin, buffer) ; result = maxDetectRead (pin, buffer) ;
if (!result) if (!result)
return FALSE ; return false ;
*rh = (buffer [0] * 256 + buffer [1]) ; *rh = (buffer [0] * 256 + buffer [1]) ;
*temp = (buffer [2] * 256 + buffer [3]) ; *temp = (buffer [2] * 256 + buffer [3]) ;
@@ -229,10 +225,10 @@ int readRHT03 (const int pin, int *temp, int *rh)
// (which does seem to happen - no realtime here) // (which does seem to happen - no realtime here)
if ((*rh > 999) || (*temp > 800) || (*temp < -400)) if ((*rh > 999) || (*temp > 800) || (*temp < -400))
return FALSE ; return false ;
lastRh = *rh ; lastRh = *rh ;
lastTemp = *temp ; lastTemp = *temp ;
return TRUE ; return true ;
} }

View File

@@ -473,7 +473,7 @@ static void wfi(struct WPIWfiStatus wfiStatus, void* userdata) {
edgeType = "falling"; edgeType = "falling";
else else
edgeType = "none"; edgeType = "none";
printf("gpio BCM = %d, IRQ edge = %s, timestamp = %lld microseconds, timenow = %lld, diff = %lld\n", wfiStatus.gpioPin, edgeType, wfiStatus.timeStamp_us, timenow, diff); printf("gpio BCM = %d, IRQ edge = %s, timestamp = %lld microseconds, timenow = %lld, diff = %lld\n", wfiStatus.pinBCM, edgeType, wfiStatus.timeStamp_us, timenow, diff);
if (toggle == 0) { if (toggle == 0) {
digitalWrite (OUTpin, HIGH); digitalWrite (OUTpin, HIGH);
toggle = 1; toggle = 1;
@@ -500,19 +500,19 @@ int main (void)
printf("Testing waitForInterrupt on both edges IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT); printf("Testing waitForInterrupt on both edges IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT);
struct WPIWfiStatus wfiStatus = waitForInterrupt2(IRQpin, INT_EDGE_BOTH, TIMEOUT, BOUNCETIME_WFI); struct WPIWfiStatus wfiStatus = waitForInterrupt2(IRQpin, INT_EDGE_BOTH, TIMEOUT, BOUNCETIME_WFI);
if (wfiStatus.status < 0) { if (wfiStatus.statusOK < 0) {
printf("waitForInterrupt returned error\n"); printf("waitForInterrupt returned error\n");
pinMode(OUTpin, INPUT); pinMode(OUTpin, INPUT);
return 0; return 0;
} }
else if (wfiStatus.status == 0) { else if (wfiStatus.statusOK == 0) {
printf("waitForInterrupt timed out\n\n"); printf("waitForInterrupt timed out\n\n");
} }
else { else {
if (wfiStatus.edge == INT_EDGE_FALLING) if (wfiStatus.edge == INT_EDGE_FALLING)
printf("waitForInterrupt: GPIO pin %d falling edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us); printf("waitForInterrupt: GPIO pin %d falling edge fired at %lld microseconds\n\n", wfiStatus.pinBCM, wfiStatus.timeStamp_us);
else else
printf("waitForInterrupt: GPIO pin %d rising edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us); printf("waitForInterrupt: GPIO pin %d rising edge fired at %lld microseconds\n\n", wfiStatus.pinBCM, wfiStatus.timeStamp_us);
} }
printf("Testing IRQ @ GPIO%d on both edges and bouncetime %d microseconds. Toggle LED @ GPIO%d on IRQ.\n\n", IRQpin, BOUNCETIME, OUTpin); printf("Testing IRQ @ GPIO%d on both edges and bouncetime %d microseconds. Toggle LED @ GPIO%d on IRQ.\n\n", IRQpin, BOUNCETIME, OUTpin);
@@ -809,8 +809,8 @@ int wiringPiSPISetupMode(int channel, int speed, int mode)
int wiringPiSPIxSetupMode(const int number, const int channel, const int speed, const int mode) int wiringPiSPIxSetupMode(const int number, const int channel, const int speed, const int mode)
``` ```
``number``: SPI Nummer (typisch 0, bei Compute Modul 0-7). ``number``: SPI Nummer (typisch 0, bei Compute Modul 0-6).
``channel``: SPI Kanal (typisch 0 oder 1, bei Compute Modul 0-3). ``channel``: SPI Kanal (typisch 0 oder 1, bei Compute Modul oder entsprechenden overlay 0-4).
``speed``: SPI Taktrate. ``speed``: SPI Taktrate.
``mode``: SPI Modus (https://www.kernel.org/doc/Documentation/spi/spidev). ``mode``: SPI Modus (https://www.kernel.org/doc/Documentation/spi/spidev).
``Rückgabewert``: Datei Handle zum SPI-Bus ``Rückgabewert``: Datei Handle zum SPI-Bus

View File

@@ -470,7 +470,7 @@ static void wfi(struct WPIWfiStatus wfiStatus, void* userdata) {
edgeType = "falling"; edgeType = "falling";
else else
edgeType = "none"; edgeType = "none";
printf("gpio BCM = %d, IRQ edge = %s, timestamp = %lld microseconds, timenow = %lld, diff = %lld\n", wfiStatus.gpioPin, edgeType, wfiStatus.timeStamp_us, timenow, diff); printf("gpio BCM = %d, IRQ edge = %s, timestamp = %lld microseconds, timenow = %lld, diff = %lld\n", wfiStatus.pinBCM, edgeType, wfiStatus.timeStamp_us, timenow, diff);
if (toggle == 0) { if (toggle == 0) {
digitalWrite (OUTpin, HIGH); digitalWrite (OUTpin, HIGH);
toggle = 1; toggle = 1;
@@ -497,19 +497,19 @@ int main (void)
printf("Testing waitForInterrupt on both edges IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT); printf("Testing waitForInterrupt on both edges IRQ @ GPIO%d, timeout is %d\n", IRQpin, TIMEOUT);
struct WPIWfiStatus wfiStatus = waitForInterrupt2(IRQpin, INT_EDGE_BOTH, TIMEOUT, BOUNCETIME_WFI); struct WPIWfiStatus wfiStatus = waitForInterrupt2(IRQpin, INT_EDGE_BOTH, TIMEOUT, BOUNCETIME_WFI);
if (wfiStatus.status < 0) { if (wfiStatus.statusOK < 0) {
printf("waitForInterrupt returned error\n"); printf("waitForInterrupt returned error\n");
pinMode(OUTpin, INPUT); pinMode(OUTpin, INPUT);
return 0; return 0;
} }
else if (wfiStatus.status == 0) { else if (wfiStatus.statusOK == 0) {
printf("waitForInterrupt timed out\n\n"); printf("waitForInterrupt timed out\n\n");
} }
else { else {
if (wfiStatus.edge == INT_EDGE_FALLING) if (wfiStatus.edge == INT_EDGE_FALLING)
printf("waitForInterrupt: GPIO pin %d falling edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us); printf("waitForInterrupt: GPIO pin %d falling edge fired at %lld microseconds\n\n", wfiStatus.pinBCM, wfiStatus.timeStamp_us);
else else
printf("waitForInterrupt: GPIO pin %d rising edge fired at %lld microseconds\n\n", wfiStatus.gpioPin, wfiStatus.timeStamp_us); printf("waitForInterrupt: GPIO pin %d rising edge fired at %lld microseconds\n\n", wfiStatus.pinBCM, wfiStatus.timeStamp_us);
} }
printf("Testing IRQ @ GPIO%d on both edges and bouncetime %d microseconds. Toggle LED @ GPIO%d on IRQ.\n\n", IRQpin, BOUNCETIME, OUTpin); printf("Testing IRQ @ GPIO%d on both edges and bouncetime %d microseconds. Toggle LED @ GPIO%d on IRQ.\n\n", IRQpin, BOUNCETIME, OUTpin);
@@ -798,8 +798,8 @@ int wiringPiSPISetupMode(int channel, int speed, int mode);
int wiringPiSPIxSetupMode(const int number, const int channel, const int speed, const int mode); int wiringPiSPIxSetupMode(const int number, const int channel, const int speed, const int mode);
``` ```
``number``: SPI number (typically 0, on Compute Module 0-7). ``number``: SPI number (typically 0, on Compute Module 0-6).
``channel``: SPI channel (typically 0 or 1, on Compute Module 0-3). ``channel``: SPI channel (typically 0 or 1, on Compute Module or the corresponding overlay 0-4).
``speed``: SPI clock speed in Hz (500,000 to 32,000,000). ``speed``: SPI clock speed in Hz (500,000 to 32,000,000).
``mode``: SPI mode ([www.kernel.org/doc/Documentation/spi/spidev](https://www.kernel.org/doc/Documentation/spi/spidev)). ``mode``: SPI mode ([www.kernel.org/doc/Documentation/spi/spidev](https://www.kernel.org/doc/Documentation/spi/spidev)).
``Return Value``: File handle to the SPI bus, or -1 on error. ``Return Value``: File handle to the SPI bus, or -1 on error.

View File

@@ -18,16 +18,12 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <sys/time.h> #include <sys/time.h>
#include <wiringPi.h> #include <wiringPi.h>
#include <gertboard.h> #include <gertboard.h>
#ifndef TRUE
#define TRUE (1==1)
#define FALSE (!TRUE)
#endif
#define B_SIZE 1000 #define B_SIZE 1000
#define S_SIZE 128 #define S_SIZE 128

View File

@@ -7,17 +7,13 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include <math.h> #include <math.h>
#include <wiringPi.h> #include <wiringPi.h>
#include <piFace.h> #include <piFace.h>
#ifndef TRUE
# define TRUE (1==1)
# define FALSE (1==2)
#endif
#undef DEBUG #undef DEBUG
#define NUM_LEDS 8 #define NUM_LEDS 8
@@ -244,7 +240,7 @@ void ledOnAction (void)
if (digitalRead (PIFACE) == LOW) if (digitalRead (PIFACE) == LOW)
{ {
chargeCapacitor () ; chargeCapacitor () ;
ledBargraph (vCap, TRUE) ; ledBargraph (vCap, true) ;
} }
} }
@@ -264,7 +260,7 @@ void ledOffAction (void)
if (digitalRead (PIFACE) == LOW) if (digitalRead (PIFACE) == LOW)
{ {
vCap = vCapLast = 0.0 ; vCap = vCapLast = 0.0 ;
ledBargraph (vCap, FALSE) ; ledBargraph (vCap, false) ;
// Wait until we release the button // Wait until we release the button
@@ -300,7 +296,7 @@ int main (void)
// LED ON: // LED ON:
(void)ledBargraph (vCap, TRUE) ; (void)ledBargraph (vCap, true) ;
then = millis () + ledOnTime ; then = millis () + ledOnTime ;
while (millis () < then) while (millis () < then)
{ {
@@ -323,7 +319,7 @@ int main (void)
// LED OFF: // LED OFF:
(void)ledBargraph (vCap, FALSE) ; (void)ledBargraph (vCap, false) ;
then = millis () + ledOffTime ; then = millis () + ledOffTime ;
while (millis () < then) while (millis () < then)
{ {

View File

@@ -25,6 +25,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <poll.h> #include <poll.h>
#include <wiringPi.h> #include <wiringPi.h>
@@ -32,11 +33,6 @@
#define PIGLOW_BASE 533 #define PIGLOW_BASE 533
#ifndef TRUE
# define TRUE (1==1)
# define FALSE (!TRUE)
#endif
/* /*
* keypressed: clearKeypressed: * keypressed: clearKeypressed:

View File

@@ -26,11 +26,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#ifndef TRUE
# define TRUE (1==1)
# define FALSE (!TRUE)
#endif
#include <wiringPi.h> #include <wiringPi.h>
#include <piGlow.h> #include <piGlow.h>
@@ -81,7 +77,7 @@ int main (int argc, char *argv [])
// Initialise the piGlow devLib // Initialise the piGlow devLib
piGlowSetup (FALSE) ; piGlowSetup (false) ;
if (argc == 1) if (argc == 1)
failUsage () ; failUsage () ;

View File

@@ -35,6 +35,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
@@ -45,11 +46,6 @@
#include <wiringPi.h> #include <wiringPi.h>
#include <lcd128x64.h> #include <lcd128x64.h>
#ifndef TRUE
# define TRUE (1==1)
# define FALSE (1==2)
#endif
double clockRadius ; double clockRadius ;
double thickness, barLen ; double thickness, barLen ;
int maxX, maxY ; int maxX, maxY ;
@@ -130,15 +126,15 @@ void drawClockFace (void)
double d, px1, py1, px2, py2 ; double d, px1, py1, px2, py2 ;
lcd128x64clear (0) ; lcd128x64clear (0) ;
lcd128x64circle (0,0, clockRadius, 1, TRUE) ; lcd128x64circle (0,0, clockRadius, 1, true) ;
lcd128x64circle (0,0, clockRadius - thickness, 0, TRUE) ; lcd128x64circle (0,0, clockRadius - thickness, 0, true) ;
// The four big indicators for 12,15,30 and 45 // The four big indicators for 12,15,30 and 45
lcd128x64rectangle (- 3, clockRadius - barLen, 3, clockRadius, 1, TRUE) ; // 12 lcd128x64rectangle (- 3, clockRadius - barLen, 3, clockRadius, 1, true) ; // 12
lcd128x64rectangle (clockRadius - barLen, 3, clockRadius, -3, 1, TRUE) ; // 3 lcd128x64rectangle (clockRadius - barLen, 3, clockRadius, -3, 1, true) ; // 3
lcd128x64rectangle (- 3, -clockRadius + barLen, 3, -clockRadius, 1, TRUE) ; // 6 lcd128x64rectangle (- 3, -clockRadius + barLen, 3, -clockRadius, 1, true) ; // 6
lcd128x64rectangle (-clockRadius + barLen, 3, -clockRadius, -3, 1, TRUE) ; // 9 lcd128x64rectangle (-clockRadius + barLen, 3, -clockRadius, -3, 1, true) ; // 9
// Smaller 5 and 1 minute ticks // Smaller 5 and 1 minute ticks

View File

@@ -26,6 +26,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
@@ -34,11 +35,6 @@
#include <mcp23017.h> #include <mcp23017.h>
#include <lcd.h> #include <lcd.h>
#ifndef TRUE
# define TRUE (1==1)
# define FALSE (1==2)
#endif
// Defines for the Adafruit Pi LCD interface board // Defines for the Adafruit Pi LCD interface board
@@ -251,7 +247,7 @@ int main (int argc, char *argv[])
{ {
int colour ; int colour ;
int cols = 16 ; int cols = 16 ;
int waitForRelease = FALSE ; int waitForRelease = false ;
struct tm *t ; struct tm *t ;
time_t tim ; time_t tim ;
@@ -287,13 +283,13 @@ int main (int argc, char *argv[])
lcdPuts (lcdHandle, "User Char: ") ; lcdPuts (lcdHandle, "User Char: ") ;
lcdPutchar (lcdHandle, 2) ; lcdPutchar (lcdHandle, 2) ;
lcdCursor (lcdHandle, TRUE) ; lcdCursor (lcdHandle, true) ;
lcdCursorBlink (lcdHandle, TRUE) ; lcdCursorBlink (lcdHandle, true) ;
waitForEnter () ; waitForEnter () ;
lcdCursor (lcdHandle, FALSE) ; lcdCursor (lcdHandle, false) ;
lcdCursorBlink (lcdHandle, FALSE) ; lcdCursorBlink (lcdHandle, false) ;
speedTest () ; speedTest () ;
@@ -320,7 +316,7 @@ int main (int argc, char *argv[])
if ((digitalRead (AF_UP) == LOW) || (digitalRead (AF_DOWN) == LOW)) if ((digitalRead (AF_UP) == LOW) || (digitalRead (AF_DOWN) == LOW))
continue ; continue ;
else else
waitForRelease = FALSE ; waitForRelease = false ;
} }
if (digitalRead (AF_UP) == LOW) // Pushed if (digitalRead (AF_UP) == LOW) // Pushed
@@ -329,7 +325,7 @@ int main (int argc, char *argv[])
if (colour == 8) if (colour == 8)
colour = 0 ; colour = 0 ;
setBacklightColour (colour) ; setBacklightColour (colour) ;
waitForRelease = TRUE ; waitForRelease = true ;
} }
if (digitalRead (AF_DOWN) == LOW) // Pushed if (digitalRead (AF_DOWN) == LOW) // Pushed
@@ -338,7 +334,7 @@ int main (int argc, char *argv[])
if (colour == -1) if (colour == -1)
colour = 7 ; colour = 7 ;
setBacklightColour (colour) ; setBacklightColour (colour) ;
waitForRelease = TRUE ; waitForRelease = true ;
} }
} }

View File

@@ -38,6 +38,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
@@ -47,10 +48,6 @@
#include <wiringPi.h> #include <wiringPi.h>
#include <lcd.h> #include <lcd.h>
#ifndef TRUE
# define TRUE (1==1)
# define FALSE (1==2)
#endif
static unsigned char newChar [8] = static unsigned char newChar [8] =
{ {
@@ -247,13 +244,13 @@ int main (int argc, char *argv[])
lcdPuts (lcdHandle, "User Char: ") ; lcdPuts (lcdHandle, "User Char: ") ;
lcdPutchar (lcdHandle, 2) ; lcdPutchar (lcdHandle, 2) ;
lcdCursor (lcdHandle, TRUE) ; lcdCursor (lcdHandle, true) ;
lcdCursorBlink (lcdHandle, TRUE) ; lcdCursorBlink (lcdHandle, true) ;
waitForEnter () ; waitForEnter () ;
lcdCursor (lcdHandle, FALSE) ; lcdCursor (lcdHandle, false) ;
lcdCursorBlink (lcdHandle, FALSE) ; lcdCursorBlink (lcdHandle, false) ;
lcdClear (lcdHandle) ; lcdClear (lcdHandle) ;
for (;;) for (;;)

View File

@@ -25,6 +25,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
@@ -36,9 +37,6 @@
#include <wiringPi.h> #include <wiringPi.h>
#include <wiringPiSPI.h> #include <wiringPiSPI.h>
#define TRUE (1==1)
#define FALSE (!TRUE)
#define SPI_CHAN 0 #define SPI_CHAN 0
#define NUM_TIMES 100 #define NUM_TIMES 100
#define MAX_SIZE (1024*1024) #define MAX_SIZE (1024*1024)
@@ -78,7 +76,7 @@ int main (void)
printf ("| MHz | Size | mS/Trans | TpS | Mb/Sec | Latency mS |\n") ; printf ("| MHz | Size | mS/Trans | TpS | Mb/Sec | Latency mS |\n") ;
printf ("+-------+--------+----------+----------+-----------+------------+\n") ; printf ("+-------+--------+----------+----------+-----------+------------+\n") ;
spiFail = FALSE ; spiFail = false ;
spiSetup (speed * 1000000) ; spiSetup (speed * 1000000) ;
for (size = 1 ; size <= MAX_SIZE ; size *= 2) for (size = 1 ; size <= MAX_SIZE ; size *= 2)
{ {
@@ -89,7 +87,7 @@ int main (void)
if (wiringPiSPIDataRW (SPI_CHAN, myData, size) == -1) if (wiringPiSPIDataRW (SPI_CHAN, myData, size) == -1)
{ {
printf ("SPI failure: %s\n", strerror (errno)) ; printf ("SPI failure: %s\n", strerror (errno)) ;
spiFail = TRUE ; spiFail = true ;
break ; break ;
} }
end = millis () ; end = millis () ;

View File

@@ -282,7 +282,7 @@ Please report bugs to https://github.com/WiringPi/WiringPi/issues
.SH COPYRIGHT .SH COPYRIGHT
Copyright (c) 2012-2025 Gordon Henderson and contributors Copyright (c) 20122019 Gordon Henderson; 20192026 Contributors
.br .br
This is free software; see the source for copying conditions. There is NO This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

View File

@@ -2,7 +2,7 @@
* gpio.c: * gpio.c:
* Swiss-Army-Knife, Set-UID command-line interface to the Raspberry * Swiss-Army-Knife, Set-UID command-line interface to the Raspberry
* Pi's GPIO. * Pi's GPIO.
* Copyright (c) 2012-2025 Gordon Henderson and contributors * Copyright (c) 20122019 Gordon Henderson; 20192026 Contributors
*********************************************************************** ***********************************************************************
* This file is part of wiringPi: * This file is part of wiringPi:
* https://github.com/WiringPi/WiringPi/ * https://github.com/WiringPi/WiringPi/
@@ -25,6 +25,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
@@ -51,11 +52,6 @@ extern void doReadall (void) ;
extern void doAllReadall (void) ; extern void doAllReadall (void) ;
extern void doQmode (int argc, char *argv []) ; extern void doQmode (int argc, char *argv []) ;
#ifndef TRUE
# define TRUE (1==1)
# define FALSE (1==2)
#endif
#define PI_USB_POWER_CONTROL 38 #define PI_USB_POWER_CONTROL 38
#define I2CDETECT "i2cdetect" #define I2CDETECT "i2cdetect"
#define MODPROBE "modprobe" #define MODPROBE "modprobe"
@@ -920,7 +916,7 @@ static void doVersion (char *argv [])
wiringPiVersion (&vMaj, &vMin) ; wiringPiVersion (&vMaj, &vMin) ;
printf ("gpio version: %d.%d\n", vMaj, vMin) ; printf ("gpio version: %d.%d\n", vMaj, vMin) ;
printf ("Copyright (c) 2012-2025 Gordon Henderson and contributors\n") ; printf ("Copyright (c) 20122019 Gordon Henderson; 20192026 Contributors\n") ;
printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ; printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ;
printf ("For details type: %s -warranty\n", argv [0]) ; printf ("For details type: %s -warranty\n", argv [0]) ;
printf ("\n") ; printf ("\n") ;
@@ -992,12 +988,12 @@ int main (int argc, char *argv [])
if (getenv ("WIRINGPI_DEBUG") != NULL) if (getenv ("WIRINGPI_DEBUG") != NULL)
{ {
printf ("gpio: wiringPi debug mode enabled\n") ; printf ("gpio: wiringPi debug mode enabled\n") ;
wiringPiDebug = TRUE ; wiringPiDebug = true ;
} }
if (getenv ("GPIO_DEBUG") != NULL) if (getenv ("GPIO_DEBUG") != NULL)
{ {
printf ("gpio: gpio debug mode enabled\n") ; printf ("gpio: gpio debug mode enabled\n") ;
gpioDebug = TRUE ; gpioDebug = true ;
} }
if (argc == 1) if (argc == 1)
@@ -1037,7 +1033,7 @@ int main (int argc, char *argv [])
if (strcasecmp (argv [1], "-warranty") == 0) if (strcasecmp (argv [1], "-warranty") == 0)
{ {
printf ("gpio version: %s\n", VERSION) ; printf ("gpio version: %s\n", VERSION) ;
printf ("Copyright (c) 2012-2025 Gordon Henderson and contributors\n") ; printf ("Copyright (c) 20122019 Gordon Henderson; 20192026 Contributors\n") ;
printf ("\n") ; printf ("\n") ;
printf (" This program is free software; you can redistribute it and/or modify\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") ; printf (" it under the terms of the GNU Leser General Public License as published\n") ;
@@ -1159,7 +1155,7 @@ int main (int argc, char *argv [])
exit (EXIT_FAILURE) ; exit (EXIT_FAILURE) ;
} }
if (!loadWPiExtension (argv [0], argv [2], TRUE)) if (!loadWPiExtension (argv [0], argv [2], true))
{ {
fprintf (stderr, "%s: Extension load failed: %s\n", argv [0], strerror (errno)) ; fprintf (stderr, "%s: Extension load failed: %s\n", argv [0], strerror (errno)) ;
exit (EXIT_FAILURE) ; exit (EXIT_FAILURE) ;
@@ -1209,8 +1205,8 @@ int main (int argc, char *argv [])
else if (strcasecmp (argv [1], "i2cd" ) == 0) doI2Cdetect (argv [0]) ; else if (strcasecmp (argv [1], "i2cd" ) == 0) doI2Cdetect (argv [0]) ;
else if (strcasecmp (argv [1], "reset" ) == 0) doReset (argv [0]) ; 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], "wb" ) == 0) doWriteByte (argc, argv) ;
else if (strcasecmp (argv [1], "rbx" ) == 0) doReadByte (argc, argv, TRUE) ; else if (strcasecmp (argv [1], "rbx" ) == 0) doReadByte (argc, argv, true) ;
else if (strcasecmp (argv [1], "rbd" ) == 0) doReadByte (argc, argv, FALSE) ; 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], "clock" ) == 0) doClock (argc, argv) ;
else if (strcasecmp (argv [1], "wfis" ) == 0) doWfi2 (argc, argv) ; else if (strcasecmp (argv [1], "wfis" ) == 0) doWfi2 (argc, argv) ;
else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ; else if (strcasecmp (argv [1], "wfi" ) == 0) doWfi (argc, argv) ;

View File

@@ -1,7 +1,7 @@
/* /*
* readall.c: * readall.c:
* The readall functions - getting a bit big, so split them out. * The readall functions - getting a bit big, so split them out.
* Copyright (c) 2012-2024 Gordon Henderson and contributors * Copyright (c) 20122019 Gordon Henderson; 20192026 Contributors
*********************************************************************** ***********************************************************************
* This file is part of wiringPi: * This file is part of wiringPi:
* https://github.com/WiringPi/WiringPi/ * https://github.com/WiringPi/WiringPi/
@@ -24,6 +24,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
@@ -37,11 +38,6 @@
extern int wpMode ; extern int wpMode ;
#ifndef TRUE
# define TRUE (1==1)
# define FALSE (1==2)
#endif
/* /*
* doReadallExternal: * doReadallExternal:
* A relatively crude way to read the pins on an external device. * A relatively crude way to read the pins on an external device.

90
gpio/test/gpio_test1_piface1.sh Executable file
View File

@@ -0,0 +1,90 @@
#!/bin/bash
echo -e "🔧 Starting relay unit test for MCP23S17@Piface unit test hw\n\n"
# set pin 200207 as output
for i in {200..207}; do
gpio -x mcp23s17:200:0:0 mode $i out
done
# set pin 208215 as input
for i in {208..215}; do
gpio -x mcp23s17:200:0:0 mode $i in
gpio -x mcp23s17:200:0:0 mode $i up
done
# Define relay output addresses and corresponding feedback input addresses
relay_addresses=(200 201 207 206)
feedback_addresses=(214 215 212 213)
for round in {1..3}; do
echo -e "🔄 Round $round / 3\n"
# Loop through each relay
for i in "${!relay_addresses[@]}"; do
out=${relay_addresses[$i]}
in=${feedback_addresses[$i]}
echo "➡️ Relay/IO write test $((i+1)): Address $out → Feedback at $in"
# Turn ON
gpio -x mcp23s17:200:0:0 write "$out" 1
sleep 0.5
feedback_on=$(gpio -x mcp23s17:200:0:0 read "$in")
if [ "$feedback_on" -eq 0 ]; then
echo "✅ ON Test passed: Feedback is LOW as expected."
else
echo "❌ ON Test failed: Feedback is HIGH."
fi
# Turn OFF
gpio -x mcp23s17:200:0:0 write "$out" 0
sleep 0.5
feedback_off=$(gpio -x mcp23s17:200:0:0 read "$in")
if [ "$feedback_off" -eq 1 ]; then
echo "✅ OFF Test passed: Feedback is HIGH as expected."
else
echo "❌ OFF Test failed: Feedback is LOW."
fi
echo -e "\n"
sleep 0.5
done
for addr in {208..211}; do
echo "🔃 Pullup resistor test address $addr: "
gpio -x mcp23s17:200:0:0 mode "$addr" up
sleep 0.5
feedback_on=$(gpio -x mcp23s17:200:0:0 read "$addr")
if [ "$feedback_on" -eq 1 ]; then
echo "✅ PULLUP Test passed: Feedback is HIGH as expected."
else
echo "❌ PULLUP Test failed: Feedback is LOW."
fi
sleep 0.5
gpio -x mcp23s17:200:0:0 mode "$addr" down
sleep 0.5
feedback_on=$(gpio -x mcp23s17:200:0:0 read "$addr")
if [ "$feedback_on" -eq 1 ]; then
echo "✅ PULLDOWN Test passed: Feedback is LOW as expected."
else
echo "❌ PULLDOW Test failed: Feedback is HIGH."
fi
echo -e "\n"
sleep 0.5
done
done
#echo "🧹 Cleanup complete. All relays turned OFF."

View File

@@ -1,3 +1,3 @@
#define VERSION "3.16" #define VERSION "3.18"
#define VERSION_MAJOR 3 #define VERSION_MAJOR 3
#define VERSION_MINOR 16 #define VERSION_MINOR 18

View File

@@ -35,6 +35,7 @@
#include <byteswap.h> #include <byteswap.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <wiringPi.h> #include <wiringPi.h>
#include <wiringPiI2C.h> #include <wiringPiI2C.h>
@@ -278,7 +279,7 @@ int ads1115Setup (const int pinBase, int i2cAddr)
int fd ; int fd ;
if ((fd = wiringPiI2CSetup (i2cAddr)) < 0) if ((fd = wiringPiI2CSetup (i2cAddr)) < 0)
return FALSE ; return false ;
node = wiringPiNewNode (pinBase, 8) ; node = wiringPiNewNode (pinBase, 8) ;
@@ -289,5 +290,5 @@ int ads1115Setup (const int pinBase, int i2cAddr)
node->analogWrite = myAnalogWrite ; node->analogWrite = myAnalogWrite ;
node->digitalWrite = myDigitalWrite ; node->digitalWrite = myDigitalWrite ;
return TRUE ; return true ;
} }

View File

@@ -30,6 +30,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
@@ -192,7 +193,7 @@ int bmp180Setup (const int pinBase)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if ((fd = wiringPiI2CSetup (I2C_ADDRESS)) < 0) if ((fd = wiringPiI2CSetup (I2C_ADDRESS)) < 0)
return FALSE ; return false ;
node = wiringPiNewNode (pinBase, 4) ; node = wiringPiNewNode (pinBase, 4) ;
@@ -233,5 +234,5 @@ int bmp180Setup (const int pinBase)
p1 = 1.0 - 7357.0 * pow (2.0, -20.0) ; p1 = 1.0 - 7357.0 * pow (2.0, -20.0) ;
p2 = 3038.0 * 100.0 * pow (2.0, -36.0) ; p2 = 3038.0 * 100.0 * pow (2.0, -36.0) ;
return TRUE ; return true ;
} }

View File

@@ -24,6 +24,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
@@ -342,12 +343,12 @@ int drcSetupNet (const int pinBase, const int numPins, const char *ipAddress, co
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if ((fd = _drcSetupNet (ipAddress, port, password)) < 0) if ((fd = _drcSetupNet (ipAddress, port, password)) < 0)
return FALSE ; return false ;
len = sizeof (struct drcNetComStruct) ; len = sizeof (struct drcNetComStruct) ;
if (setsockopt (fd, SOL_SOCKET, SO_RCVLOWAT, (void *)&len, sizeof (len)) < 0) if (setsockopt (fd, SOL_SOCKET, SO_RCVLOWAT, (void *)&len, sizeof (len)) < 0)
return FALSE ; return false ;
node = wiringPiNewNode (pinBase, numPins) ; node = wiringPiNewNode (pinBase, numPins) ;
@@ -361,5 +362,5 @@ int drcSetupNet (const int pinBase, const int numPins, const char *ipAddress, co
node->digitalWrite = myDigitalWrite ; node->digitalWrite = myDigitalWrite ;
node->pwmWrite = myPwmWrite ; node->pwmWrite = myPwmWrite ;
return TRUE ; return true ;
} }

View File

@@ -23,6 +23,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <time.h> #include <time.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
@@ -151,7 +152,7 @@ int drcSetupSerial (const int pinBase, const int numPins, const char *device, co
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if ((fd = serialOpen (device, baud)) < 0) if ((fd = serialOpen (device, baud)) < 0)
return FALSE ; return false ;
delay (10) ; // May need longer if it's an Uno that reboots on the open... delay (10) ; // May need longer if it's an Uno that reboots on the open...
@@ -160,7 +161,7 @@ int drcSetupSerial (const int pinBase, const int numPins, const char *device, co
while (serialDataAvail (fd)) while (serialDataAvail (fd))
(void)serialGetchar (fd) ; (void)serialGetchar (fd) ;
ok = FALSE ; ok = false ;
for (tries = 1 ; (tries < 5) && (!ok) ; ++tries) for (tries = 1 ; (tries < 5) && (!ok) ; ++tries)
{ {
serialPutchar (fd, '@') ; // Ping serialPutchar (fd, '@') ; // Ping
@@ -170,7 +171,7 @@ int drcSetupSerial (const int pinBase, const int numPins, const char *device, co
{ {
if (serialGetchar (fd) == '@') if (serialGetchar (fd) == '@')
{ {
ok = TRUE ; ok = true ;
break ; break ;
} }
} }
@@ -179,7 +180,7 @@ int drcSetupSerial (const int pinBase, const int numPins, const char *device, co
if (!ok) if (!ok)
{ {
serialClose (fd) ; serialClose (fd) ;
return FALSE ; return false ;
} }
node = wiringPiNewNode (pinBase, numPins) ; node = wiringPiNewNode (pinBase, numPins) ;
@@ -192,5 +193,5 @@ int drcSetupSerial (const int pinBase, const int numPins, const char *device, co
node->digitalWrite = myDigitalWrite ; node->digitalWrite = myDigitalWrite ;
node->pwmWrite = myPwmWrite ; node->pwmWrite = myPwmWrite ;
return TRUE ; return true ;
} }

View File

@@ -29,6 +29,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <malloc.h> #include <malloc.h>
@@ -123,7 +124,7 @@ int ds18b20Setup (const int pinBase, const char *deviceId)
// Allocate space for the filename // Allocate space for the filename
if ((fileName = malloc (strlen (W1_PREFIX) + strlen (W1_POSTFIX) + strlen (deviceId) + 1)) == NULL) if ((fileName = malloc (strlen (W1_PREFIX) + strlen (W1_POSTFIX) + strlen (deviceId) + 1)) == NULL)
return FALSE ; return false ;
sprintf (fileName, "%s%s%s", W1_PREFIX, deviceId, W1_POSTFIX) ; sprintf (fileName, "%s%s%s", W1_PREFIX, deviceId, W1_POSTFIX) ;
@@ -132,7 +133,7 @@ int ds18b20Setup (const int pinBase, const char *deviceId)
free (fileName) ; free (fileName) ;
if (fd < 0) if (fd < 0)
return FALSE ; return false ;
// We'll keep the file open, to make access a little faster // We'll keep the file open, to make access a little faster
// although it's very slow reading these things anyway )-: // although it's very slow reading these things anyway )-:
@@ -142,5 +143,5 @@ int ds18b20Setup (const int pinBase, const char *deviceId)
node->fd = fd ; node->fd = fd ;
node->analogRead = myAnalogRead ; node->analogRead = myAnalogRead ;
return TRUE ; return true ;
} }

2
wiringPi/gtest/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
bin
googletest-main

92
wiringPi/gtest/Makefile Normal file
View File

@@ -0,0 +1,92 @@
CXX := g++
CXXFLAGS := -std=c++17 -Wall -Wextra -Werror -g \
-Igoogletest-main/googletest/include -Igoogletest-main/googlemock/include
LDFLAGS := -pthread
WIRING_PI_LIBS := -lwiringPi
# Where to download googletest
GTEST_URL := https://github.com/google/googletest/archive/refs/heads/main.zip
GTEST_ZIP := googletest.zip
GTEST_DIR := googletest-main
# Output directory
BIN_DIR := bin
# Helper program
RUN_ISR_SRC := run_isr.cpp
RUN_ISR_BIN := $(BIN_DIR)/run_isr
# Need BCM17 <-> BCM18 connection
TEST_SRCS := \
test_isr_both.cpp \
test_isr_conflict_between_processes.cpp \
test_isr_falling.cpp \
test_isr_restart.cpp \
test_isr_restart2.cpp \
test_isr_rising.cpp \
test_isr_rising2.cpp
# Derive test binaries (in bin/)
TEST_BINS := $(addprefix $(BIN_DIR)/, $(TEST_SRCS:.cpp=))
# gtest/gmock sources
GTEST_SRCS := $(GTEST_DIR)/googletest/src/gtest-all.cc
GMOCK_SRCS := $(GTEST_DIR)/googlemock/src/gmock-all.cc
GTEST_MAIN := $(GTEST_DIR)/googletest/src/gtest_main.cc
GTEST_INCLUDES := -I$(GTEST_DIR)/googletest/include -I$(GTEST_DIR)/googlemock/include
GTEST_OBJS := $(GTEST_SRCS:.cc=.o)
GMOCK_OBJS := $(GMOCK_SRCS:.cc=.o)
GTEST_MAIN_OBJ := $(GTEST_MAIN:.cc=.o)
# Default: build everything
all: $(GTEST_DIR) $(BIN_DIR) $(TEST_BINS) $(RUN_ISR_BIN)
# Rule: build normal test binaries
$(filter-out $(BIN_DIR)/test_conflict_between_processes,$(TEST_BINS)): $(BIN_DIR)/%: %.cpp $(GTEST_OBJS) $(GMOCK_OBJS) $(GTEST_MAIN_OBJ)
$(CXX) $(CXXFLAGS) $< $(GTEST_OBJS) $(GMOCK_OBJS) $(GTEST_MAIN_OBJ) -o $@ $(LDFLAGS) $(WIRING_PI_LIBS)
# Special case: test_conflict_between_processes depends on run_isr
$(BIN_DIR)/test_conflict_between_processes: test_conflict_between_processes.cpp $(GTEST_OBJS) $(GMOCK_OBJS) $(GTEST_MAIN_OBJ) $(RUN_ISR_BIN)
$(CXX) $(CXXFLAGS) $< $(GTEST_OBJS) $(GMOCK_OBJS) $(GTEST_MAIN_OBJ) -o $@ $(LDFLAGS) $(WIRING_PI_LIBS)
# Build run_isr
$(RUN_ISR_BIN): $(RUN_ISR_SRC) | $(BIN_DIR)
$(CXX) $(CXXFLAGS) $< -o $@ $(WIRING_PI_LIBS)
# Ensure bin directory exists
$(BIN_DIR):
mkdir -p $(BIN_DIR)
# Download googletest if not already present
$(GTEST_DIR):
@echo "Downloading GoogleTest..."
curl -L $(GTEST_URL) -o $(GTEST_ZIP)
unzip -q $(GTEST_ZIP)
rm -f $(GTEST_ZIP)
# Generic rules for compiling gtest/gmock sources
%.o: %.cc
$(CXX) $(CXXFLAGS) $(GTEST_INCLUDES) -I$(GTEST_DIR)/googletest -I$(GTEST_DIR)/googlemock -c $< -o $@
# Run all tests
test: all
@failed=0; \
for t in $(TEST_BINS); do \
echo "Running $$t..."; \
./$$t || failed=1; \
done; \
if [ $$failed -eq 0 ]; then \
echo "✅ All tests passed."; \
else \
echo "❌ Some tests failed."; \
exit 1; \
fi
clean:
rm -f $(TEST_BINS) $(RUN_ISR_BIN)
distclean: clean
rm -rf $(GTEST_DIR) $(BIN_DIR)
.PHONY: all clean distclean test

26
wiringPi/gtest/README.md Normal file
View File

@@ -0,0 +1,26 @@
## Quick Start
g++ is required to build the test cases.
Connect wPi pin 1 (BCM 18) and wPi pin 0 (BCM 17) to run ISR tests.
Also, wPi pin 6 (BCM 25) should be unconnected.
Run `make test` or do following to run the test:
```
make googletest-main
make -j 4
make test
```
To clean up the environment:
```
make clean
```
## Dependencies
Googletest is downloaded during
the build for the first time. The downloaded items are in directory `googletest-main`. `make clean` keeps this directory. Run `make distclean`
to erase all built images including googletest.

View File

@@ -0,0 +1,31 @@
/*
* Helper program of test_conflict_between_processes.
*
* The program configures ISR on pin 1 (BCM 18) and polls for a termination request.
*/
#include <stdint.h>
#include <stdio.h>
#include <wiringPi.h>
#define LISTENER_PIN 1 // BCM 18
static uint8_t ok_to_stop = 0;
static void noop() {
fprintf(stderr, "interrupted\n");
ok_to_stop = 1;
}
int main(int, char *[]) {
fprintf(stderr, "start\n");
wiringPiSetup();
if (wiringPiISR(LISTENER_PIN, INT_EDGE_RISING, noop)) {
fprintf(stderr, "failed to start listener\n");
return -1;
}
fprintf(stderr, "start listening\n");
while (!ok_to_stop) {
delay(1000);
}
fprintf(stderr, "bye\n");
}

View File

@@ -0,0 +1,51 @@
#include <gtest/gtest.h>
#include <time.h>
#include <wiringPi.h>
#define TRIGGER_PIN 0 // BCM 17
#define LISTENER_PIN 1 // BCM 18
/**
* Tests ISR for both edges.
*/
class ISRBoth : public ::testing::Test {
public:
static void SetUpTestSuite() {
wiringPiSetup();
pinMode(TRIGGER_PIN, OUTPUT);
digitalWrite(TRIGGER_PIN, LOW);
wiringPiISR(LISTENER_PIN, INT_EDGE_BOTH, ISRBoth::TriggerCount);
delay(100);
}
static uint32_t count;
static void TriggerCount() { ++count; }
protected:
virtual void SetUp() { count = 0; }
virtual void TearDown() {
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
}
};
uint32_t ISRBoth::count = 0;
TEST_F(ISRBoth, Fundamental) {
EXPECT_EQ(count, 0u);
digitalWrite(TRIGGER_PIN, HIGH);
delay(10);
EXPECT_EQ(count, 1u);
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
EXPECT_EQ(count, 2u);
}
TEST_F(ISRBoth, ThreeTriggers) {
for (int i = 0; i < 5; ++i) {
digitalWrite(TRIGGER_PIN, (i + 1) % 2);
delay(10);
}
EXPECT_EQ(count, 5u);
}

View File

@@ -0,0 +1,68 @@
#include <gtest/gtest.h>
#include <pthread.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <wiringPi.h>
#define TRIGGER_PIN 0 // BCM 17
#define LISTENER_PIN 1 // BCM 18
#define ANOTHER_LISTENER_PIN 6 // BCM 25
static void *remote_isr(void *) {
std::system("./bin/run_isr");
return NULL;
}
/**
* Tests ISR setup conflict between two processes.
*
* Another program 'run_isr' starts first that occupies the pin 31 for an ISR.
* This program should fail to start ISR on the same pin.
*/
class ISRConflict : public ::testing::Test {
public:
static void SetUpTestSuite() {
wiringPiSetup();
digitalWrite(TRIGGER_PIN, LOW);
pthread_t tid;
pthread_create(&tid, NULL, remote_isr, NULL);
delay(1000);
}
static void TearDownTestSuite() {
delay(1000);
}
static uint32_t count;
static void TriggerCount() { ++count; }
static void TriggerCount2(WPIWfiStatus, void *userdata) {
++*(uint32_t *)userdata;
}
protected:
virtual void SetUp() { count = 0; }
virtual void TearDown() {
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
}
};
uint32_t ISRConflict::count = 0;
TEST_F(ISRConflict, TestConflictBetweenProcesses) {
// The ISRs should fail to start because run_isr is listening on the
// same port
EXPECT_EQ(
wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRConflict::TriggerCount),
-1);
EXPECT_EQ(wiringPiISR2(LISTENER_PIN, INT_EDGE_FALLING,
ISRConflict::TriggerCount2, 0, &ISRConflict::count),
-1);
// to exit run_isr
digitalWrite(TRIGGER_PIN, HIGH);
}

View File

@@ -0,0 +1,57 @@
#include <gtest/gtest.h>
#include <time.h>
#include <wiringPi.h>
#define TRIGGER_PIN 0 // BCM 17
#define LISTENER_PIN 1 // BCM 18
/**
* Tests ISR for falling edges.
*/
class ISRFalling : public ::testing::Test {
public:
static void SetUpTestSuite() {
wiringPiSetup();
pinMode(TRIGGER_PIN, OUTPUT);
digitalWrite(TRIGGER_PIN, HIGH);
wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRFalling::TriggerCount);
delay(100);
}
static void TearDownTestSuite() { digitalWrite(TRIGGER_PIN, LOW); }
static uint32_t count;
static void TriggerCount() { ++count; }
protected:
virtual void SetUp() { count = 0; }
virtual void TearDown() {
digitalWrite(TRIGGER_PIN, HIGH);
delay(10);
}
};
uint32_t ISRFalling::count = 0;
TEST_F(ISRFalling, Fundamental) {
EXPECT_EQ(count, 0u);
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
EXPECT_EQ(count, 1u);
digitalWrite(TRIGGER_PIN, HIGH);
delay(10);
EXPECT_EQ(count, 1u);
}
TEST_F(ISRFalling, ThreeTriggers) {
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
count = 0;
for (int i = 0; i < 6; ++i) {
delay(10);
digitalWrite(TRIGGER_PIN, (i + 1) % 2);
}
delay(10);
EXPECT_EQ(count, 3u);
}

View File

@@ -0,0 +1,68 @@
#include <gtest/gtest.h>
#include <time.h>
#include <wiringPi.h>
#define TRIGGER_PIN 0 // BCM 17
#define LISTENER_PIN 1 // BCM 18
#define ANOTHER_LISTENER_PIN 6 // BCM 25
/**
* Tests restarting ISR.
*/
class ISRRestart : public ::testing::Test {
public:
static void SetUpTestSuite() {
wiringPiSetup();
pinMode(TRIGGER_PIN, OUTPUT);
digitalWrite(TRIGGER_PIN, LOW);
wiringPiISR(LISTENER_PIN, INT_EDGE_RISING, ISRRestart::TriggerCount);
delay(100);
}
static uint32_t count;
static void TriggerCount() { ++count; }
static void TriggerCountDown() { --count; }
protected:
virtual void SetUp() { count = 0; }
virtual void TearDown() {
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
}
};
uint32_t ISRRestart::count = 0;
TEST_F(ISRRestart, RestartISR) {
// fundamental ISR test
EXPECT_EQ(count, 0u);
digitalWrite(TRIGGER_PIN, HIGH);
delay(10);
EXPECT_EQ(count, 1u);
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
EXPECT_EQ(count, 1u);
// stop the ISR
EXPECT_EQ(wiringPiISRStop(LISTENER_PIN), 0);
digitalWrite(TRIGGER_PIN, HIGH);
delay(10);
EXPECT_EQ(count, 1u);
digitalWrite(TRIGGER_PIN, LOW);
// start another ISR on the same pin
EXPECT_EQ(
wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRRestart::TriggerCountDown),
0);
count=1;
delay(100);
digitalWrite(TRIGGER_PIN, HIGH);
delay(10);
EXPECT_EQ(count, 1u);
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
EXPECT_EQ(count, 0u);
}

View File

@@ -0,0 +1,109 @@
#include <gtest/gtest.h>
#include <time.h>
#include <wiringPi.h>
#define TRIGGER_PIN 0 // BCM 17
#define LISTENER_PIN 1 // BCM 18
#define ANOTHER_LISTENER_PIN 26 // BCM 12
struct counters {
int32_t *primary;
int32_t *secondary;
};
/**
* Tests restarting ISR using function wiringPiISR2().
*/
class ISRRestart2 : public ::testing::Test {
public:
static void SetUpTestSuite() {
wiringPiSetup();
pinMode(TRIGGER_PIN, OUTPUT);
digitalWrite(TRIGGER_PIN, LOW);
counters_a.primary = &count;
counters_a.secondary = &count2;
counters_b.primary = &count;
counters_b.secondary = &count3;
wiringPiISR2(LISTENER_PIN, INT_EDGE_RISING, ISRRestart2::TriggerCount, 1000,
&counters_a);
delay(100);
}
static int32_t count;
static int32_t count2;
static int32_t count3;
static counters counters_a;
static counters counters_b;
static void TriggerCount(WPIWfiStatus, void *userdata) {
struct counters *counters = (struct counters *)userdata;
++*counters->primary;
++*counters->secondary;
}
static void TriggerCountDown(WPIWfiStatus, void *userdata) {
struct counters *counters = (struct counters *)userdata;
++*counters->primary;
--*counters->secondary;
}
protected:
virtual void SetUp() {
count = 0;
count2 = 0;
count3 = 0;
}
virtual void TearDown() {
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
}
};
int32_t ISRRestart2::count = 0;
int32_t ISRRestart2::count2 = 0;
int32_t ISRRestart2::count3 = 0;
struct counters ISRRestart2::counters_a;
struct counters ISRRestart2::counters_b;
TEST_F(ISRRestart2, RestartISR2) {
// fundamental ISR2 test
EXPECT_EQ(count, 0);
EXPECT_EQ(count2, 0);
digitalWrite(TRIGGER_PIN, HIGH);
delay(20);
EXPECT_EQ(count, 1);
EXPECT_EQ(count2, 1);
digitalWrite(TRIGGER_PIN, LOW);
delay(20);
EXPECT_EQ(count, 1);
EXPECT_EQ(count2, 1);
// stop the ISR
EXPECT_EQ(wiringPiISRStop(LISTENER_PIN), 0);
delay(100);
digitalWrite(TRIGGER_PIN, HIGH);
delay(20);
EXPECT_EQ(count, 1);
EXPECT_EQ(count2, 1);
EXPECT_EQ(count3, 0);
digitalWrite(TRIGGER_PIN, LOW);
// start another ISR2 on the same pin
EXPECT_EQ(wiringPiISR2(LISTENER_PIN, INT_EDGE_FALLING,
ISRRestart2::TriggerCountDown, 0, &counters_b),
0);
delay(100);
digitalWrite(TRIGGER_PIN, HIGH);
delay(20);
EXPECT_EQ(count, 1);
EXPECT_EQ(count2, 1);
EXPECT_EQ(count3, 0);
digitalWrite(TRIGGER_PIN, LOW);
delay(20);
EXPECT_EQ(count, 2);
EXPECT_EQ(count2, 1);
EXPECT_EQ(count3, -1);
}

View File

@@ -0,0 +1,80 @@
#include <gtest/gtest.h>
#include <time.h>
#include <wiringPi.h>
#define TRIGGER_PIN 0 // BCM 17
#define LISTENER_PIN 1 // BCM 18
#define ANOTHER_LISTENER_PIN 26 // BCM 12
/**
* Tests ISR for rising edges.
*/
class ISRRising : public ::testing::Test {
public:
static void SetUpTestSuite() {
wiringPiSetup();
pinMode(TRIGGER_PIN, OUTPUT);
digitalWrite(TRIGGER_PIN, LOW);
wiringPiISR(LISTENER_PIN, INT_EDGE_RISING, ISRRising::TriggerCount);
delay(100);
}
static uint32_t count;
static void TriggerCount() { ++count; }
static void TriggerCountDown() { --count; }
protected:
virtual void SetUp() { count = 0; }
virtual void TearDown() {
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
}
};
uint32_t ISRRising::count = 0;
TEST_F(ISRRising, Fundamental) {
EXPECT_EQ(count, 0u);
digitalWrite(TRIGGER_PIN, HIGH);
delay(10);
EXPECT_EQ(count, 1u);
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
EXPECT_EQ(count, 1u);
}
TEST_F(ISRRising, ThreeTriggers) {
digitalWrite(TRIGGER_PIN, HIGH);
delay(10);
count = 0;
for (int i = 0; i < 6; ++i) {
delay(10);
digitalWrite(TRIGGER_PIN, i % 2);
}
delay(10);
EXPECT_EQ(count, 3u);
}
TEST_F(ISRRising, ISRInitConflict) {
// this initialization should fail for ISR conflict
EXPECT_EQ(
wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRRising::TriggerCountDown),
-1);
// ensure the initialization above has released the mutex lock
EXPECT_EQ(wiringPiISR(ANOTHER_LISTENER_PIN, INT_EDGE_RISING,
ISRRising::TriggerCountDown),
0);
delay(100);
// ensure the existing ISR has not broken
EXPECT_EQ(count, 0u);
digitalWrite(TRIGGER_PIN, HIGH);
delay(10);
EXPECT_EQ(count, 1u);
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
EXPECT_EQ(count, 1u);
}

View File

@@ -0,0 +1,135 @@
#include <gtest/gtest.h>
#include <time.h>
#include <wiringPi.h>
#define TRIGGER_PIN 0 // BCM 17
#define LISTENER_PIN 1 // BCM 18
#define ANOTHER_LISTENER_PIN 26 // BCM 12
struct counters {
uint32_t *primary;
uint32_t *secondary;
};
/**
* Tests ISR for rising edges.
* Function wiringPiISR2 is used for the configuraiton.
*/
class ISRRising2 : public ::testing::Test {
public:
static void SetUpTestSuite() {
wiringPiSetup();
pinMode(TRIGGER_PIN, OUTPUT);
digitalWrite(TRIGGER_PIN, LOW);
counters_a.primary = &count;
counters_a.secondary = &count2;
counters_b.primary = &count;
counters_b.secondary = &count3;
wiringPiISR2(LISTENER_PIN, INT_EDGE_RISING, ISRRising2::TriggerCount, 1000,
&counters_a);
delay(100);
}
static uint32_t count;
static uint32_t count2;
static uint32_t count3;
static counters counters_a;
static counters counters_b;
static void TriggerCount(WPIWfiStatus, void *userdata) {
struct counters *counters = (struct counters *)userdata;
++*counters->primary;
++*counters->secondary;
}
static void TriggerCountDown(WPIWfiStatus, void *userdata) {
struct counters *counters = (struct counters *)userdata;
++*counters->primary;
--*counters->secondary;
}
protected:
virtual void SetUp() {
count = 0;
count2 = 0;
count3 = 0;
}
virtual void TearDown() {
digitalWrite(TRIGGER_PIN, LOW);
delay(10);
}
};
uint32_t ISRRising2::count = 0;
uint32_t ISRRising2::count2 = 0;
uint32_t ISRRising2::count3 = 0;
struct counters ISRRising2::counters_a;
struct counters ISRRising2::counters_b;
TEST_F(ISRRising2, Fundamental) {
EXPECT_EQ(count, 0u);
EXPECT_EQ(count2, 0u);
digitalWrite(TRIGGER_PIN, HIGH);
delay(20);
EXPECT_EQ(count, 1u);
EXPECT_EQ(count2, 1u);
digitalWrite(TRIGGER_PIN, LOW);
delay(20);
EXPECT_EQ(count, 1u);
EXPECT_EQ(count2, 1u);
}
TEST_F(ISRRising2, ThreeTriggers) {
digitalWrite(TRIGGER_PIN, HIGH);
delay(10);
count = 0;
for (int i = 0; i < 6; ++i) {
digitalWrite(TRIGGER_PIN, i % 2);
delay(20);
}
EXPECT_EQ(count, 3u);
}
TEST_F(ISRRising2, Debounce) {
delay(20);
for (int i = 0; i < 7; ++i) {
digitalWrite(TRIGGER_PIN, (i + 1) % 2);
}
delay(20);
EXPECT_EQ(count, 1u);
}
TEST_F(ISRRising2, ISRInitConflict) {
// this initialization should fail for ISR conflict
EXPECT_EQ(wiringPiISR2(LISTENER_PIN, INT_EDGE_FALLING,
ISRRising2::TriggerCountDown, 0, &counters_b),
-1);
// ensure the initialization above has released the mutex lock
EXPECT_EQ(wiringPiISR2(ANOTHER_LISTENER_PIN, INT_EDGE_BOTH,
ISRRising2::TriggerCountDown, 0, &counters_b),
0);
delay(100);
// ensure the existing ISR has not broken
EXPECT_EQ(count, 0u);
EXPECT_EQ(count2, 0u);
digitalWrite(TRIGGER_PIN, HIGH);
delay(20);
EXPECT_EQ(count, 1u);
EXPECT_EQ(count2, 1u);
digitalWrite(TRIGGER_PIN, LOW);
delay(20);
EXPECT_EQ(count, 1u);
EXPECT_EQ(count2, 1u);
delay(20);
count = 0;
for (int i = 0; i < 7; ++i) {
delay(1);
digitalWrite(TRIGGER_PIN, (i + 1) % 2);
}
delay(20);
EXPECT_EQ(count, 1u);
}

View File

@@ -25,6 +25,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <math.h> #include <math.h>
@@ -40,7 +41,7 @@
int checksum (UNU uint8_t data [4]) int checksum (UNU uint8_t data [4])
{ {
return TRUE ; return true ;
} }
@@ -127,7 +128,7 @@ int htu21dSetup (const int pinBase)
int status ; int status ;
if ((fd = wiringPiI2CSetup (I2C_ADDRESS)) < 0) if ((fd = wiringPiI2CSetup (I2C_ADDRESS)) < 0)
return FALSE ; return false ;
node = wiringPiNewNode (pinBase, 2) ; node = wiringPiNewNode (pinBase, 2) ;
@@ -138,7 +139,7 @@ int htu21dSetup (const int pinBase)
data = 0xFE ; data = 0xFE ;
if (write (fd, &data, 1) != 1) if (write (fd, &data, 1) != 1)
return FALSE ; return false ;
delay (15) ; delay (15) ;
@@ -146,5 +147,5 @@ int htu21dSetup (const int pinBase)
status = wiringPiI2CReadReg8 (fd, 0xE7) ; status = wiringPiI2CReadReg8 (fd, 0xE7) ;
return (status == 0x02) ? TRUE : FALSE ; return (status == 0x02) ? true : false ;
} }

View File

@@ -24,6 +24,7 @@
#include <byteswap.h> #include <byteswap.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <wiringPi.h> #include <wiringPi.h>
#include <wiringPiSPI.h> #include <wiringPiSPI.h>
@@ -88,12 +89,12 @@ int max31855Setup (const int pinBase, int spiChannel)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if (wiringPiSPISetup (spiChannel, 5000000) < 0) // 5MHz - prob 4 on the Pi if (wiringPiSPISetup (spiChannel, 5000000) < 0) // 5MHz - prob 4 on the Pi
return FALSE ; return false ;
node = wiringPiNewNode (pinBase, 4) ; node = wiringPiNewNode (pinBase, 4) ;
node->fd = spiChannel ; node->fd = spiChannel ;
node->analogRead = myAnalogRead ; node->analogRead = myAnalogRead ;
return TRUE ; return true ;
} }

View File

@@ -22,6 +22,8 @@
*********************************************************************** ***********************************************************************
*/ */
#include <stdbool.h>
#include <wiringPi.h> #include <wiringPi.h>
#include <wiringPiSPI.h> #include <wiringPiSPI.h>
@@ -66,7 +68,7 @@ int max5322Setup (const int pinBase, int spiChannel)
unsigned char spiData [2] ; unsigned char spiData [2] ;
if (wiringPiSPISetup (spiChannel, 8000000) < 0) // 10MHz Max if (wiringPiSPISetup (spiChannel, 8000000) < 0) // 10MHz Max
return FALSE ; return false ;
node = wiringPiNewNode (pinBase, 2) ; node = wiringPiNewNode (pinBase, 2) ;
@@ -80,5 +82,5 @@ int max5322Setup (const int pinBase, int spiChannel)
wiringPiSPIDataRW (node->fd, spiData, 2) ; wiringPiSPIDataRW (node->fd, spiData, 2) ;
return TRUE ; return true ;
} }

View File

@@ -23,6 +23,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <pthread.h> #include <pthread.h>
#include "wiringPi.h" #include "wiringPi.h"
@@ -132,7 +133,7 @@ int mcp23008Setup (const int pinBase, const int i2cAddress)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) if ((fd = wiringPiI2CSetup (i2cAddress)) < 0)
return FALSE ; return false ;
wiringPiI2CWriteReg8 (fd, MCP23x08_IOCON, IOCON_INIT) ; wiringPiI2CWriteReg8 (fd, MCP23x08_IOCON, IOCON_INIT) ;
@@ -145,5 +146,5 @@ int mcp23008Setup (const int pinBase, const int i2cAddress)
node->digitalWrite = myDigitalWrite ; node->digitalWrite = myDigitalWrite ;
node->data2 = wiringPiI2CReadReg8 (fd, MCP23x08_OLAT) ; node->data2 = wiringPiI2CReadReg8 (fd, MCP23x08_OLAT) ;
return TRUE ; return true ;
} }

View File

@@ -23,6 +23,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <pthread.h> #include <pthread.h>
#include "wiringPi.h" #include "wiringPi.h"
@@ -146,7 +147,7 @@ int mcp23016Setup (const int pinBase, const int i2cAddress)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) if ((fd = wiringPiI2CSetup (i2cAddress)) < 0)
return FALSE ; return false ;
wiringPiI2CWriteReg8 (fd, MCP23016_IOCON0, IOCON_INIT) ; wiringPiI2CWriteReg8 (fd, MCP23016_IOCON0, IOCON_INIT) ;
wiringPiI2CWriteReg8 (fd, MCP23016_IOCON1, IOCON_INIT) ; wiringPiI2CWriteReg8 (fd, MCP23016_IOCON1, IOCON_INIT) ;
@@ -160,5 +161,5 @@ int mcp23016Setup (const int pinBase, const int i2cAddress)
node->data2 = wiringPiI2CReadReg8 (fd, MCP23016_OLAT0) ; node->data2 = wiringPiI2CReadReg8 (fd, MCP23016_OLAT0) ;
node->data3 = wiringPiI2CReadReg8 (fd, MCP23016_OLAT1) ; node->data3 = wiringPiI2CReadReg8 (fd, MCP23016_OLAT1) ;
return TRUE ; return true ;
} }

View File

@@ -23,6 +23,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <pthread.h> #include <pthread.h>
#include "wiringPi.h" #include "wiringPi.h"
@@ -177,7 +178,7 @@ int mcp23017Setup (const int pinBase, const int i2cAddress)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) if ((fd = wiringPiI2CSetup (i2cAddress)) < 0)
return FALSE ; return false ;
wiringPiI2CWriteReg8 (fd, MCP23x17_IOCON, IOCON_INIT) ; wiringPiI2CWriteReg8 (fd, MCP23x17_IOCON, IOCON_INIT) ;
@@ -191,5 +192,5 @@ int mcp23017Setup (const int pinBase, const int i2cAddress)
node->data2 = wiringPiI2CReadReg8 (fd, MCP23x17_OLATA) ; node->data2 = wiringPiI2CReadReg8 (fd, MCP23x17_OLATA) ;
node->data3 = wiringPiI2CReadReg8 (fd, MCP23x17_OLATB) ; node->data3 = wiringPiI2CReadReg8 (fd, MCP23x17_OLATB) ;
return TRUE ; return true ;
} }

View File

@@ -24,6 +24,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "wiringPi.h" #include "wiringPi.h"
#include "wiringPiSPI.h" #include "wiringPiSPI.h"
@@ -170,7 +171,7 @@ int mcp23s08Setup (const int pinBase, const int spiPort, const int devId)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if (wiringPiSPISetup (spiPort, MCP_SPEED) < 0) if (wiringPiSPISetup (spiPort, MCP_SPEED) < 0)
return FALSE ; return false ;
writeByte (spiPort, devId, MCP23x08_IOCON, IOCON_INIT) ; writeByte (spiPort, devId, MCP23x08_IOCON, IOCON_INIT) ;
@@ -184,5 +185,5 @@ int mcp23s08Setup (const int pinBase, const int spiPort, const int devId)
node->digitalWrite = myDigitalWrite ; node->digitalWrite = myDigitalWrite ;
node->data2 = readByte (spiPort, devId, MCP23x08_OLAT) ; node->data2 = readByte (spiPort, devId, MCP23x08_OLAT) ;
return TRUE ; return true ;
} }

View File

@@ -24,6 +24,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "wiringPi.h" #include "wiringPi.h"
#include "wiringPiSPI.h" #include "wiringPiSPI.h"
@@ -215,7 +216,7 @@ int mcp23s17Setup (const int pinBase, const int spiPort, const int devId)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if (wiringPiSPISetup (spiPort, MCP_SPEED) < 0) if (wiringPiSPISetup (spiPort, MCP_SPEED) < 0)
return FALSE ; return false ;
writeByte (spiPort, devId, MCP23x17_IOCON, IOCON_INIT | IOCON_HAEN) ; writeByte (spiPort, devId, MCP23x17_IOCON, IOCON_INIT | IOCON_HAEN) ;
writeByte (spiPort, devId, MCP23x17_IOCONB, IOCON_INIT | IOCON_HAEN) ; writeByte (spiPort, devId, MCP23x17_IOCONB, IOCON_INIT | IOCON_HAEN) ;
@@ -231,5 +232,5 @@ int mcp23s17Setup (const int pinBase, const int spiPort, const int devId)
node->data2 = readByte (spiPort, devId, MCP23x17_OLATA) ; node->data2 = readByte (spiPort, devId, MCP23x17_OLATA) ;
node->data3 = readByte (spiPort, devId, MCP23x17_OLATB) ; node->data3 = readByte (spiPort, devId, MCP23x17_OLATB) ;
return TRUE ; return true ;
} }

View File

@@ -22,6 +22,8 @@
*********************************************************************** ***********************************************************************
*/ */
#include <stdbool.h>
#include <wiringPi.h> #include <wiringPi.h>
#include <wiringPiSPI.h> #include <wiringPiSPI.h>
@@ -65,12 +67,12 @@ int mcp3002Setup (const int pinBase, int spiChannel)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if (wiringPiSPISetup (spiChannel, 1000000) < 0) if (wiringPiSPISetup (spiChannel, 1000000) < 0)
return FALSE ; return false ;
node = wiringPiNewNode (pinBase, 2) ; node = wiringPiNewNode (pinBase, 2) ;
node->fd = spiChannel ; node->fd = spiChannel ;
node->analogRead = myAnalogRead ; node->analogRead = myAnalogRead ;
return TRUE ; return true ;
} }

View File

@@ -24,6 +24,8 @@
*********************************************************************** ***********************************************************************
*/ */
#include <stdbool.h>
#include <wiringPi.h> #include <wiringPi.h>
#include <wiringPiSPI.h> #include <wiringPiSPI.h>
@@ -65,12 +67,12 @@ int mcp3004Setup (const int pinBase, int spiChannel)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if (wiringPiSPISetup (spiChannel, 1000000) < 0) if (wiringPiSPISetup (spiChannel, 1000000) < 0)
return FALSE ; return false ;
node = wiringPiNewNode (pinBase, 8) ; node = wiringPiNewNode (pinBase, 8) ;
node->fd = spiChannel ; node->fd = spiChannel ;
node->analogRead = myAnalogRead ; node->analogRead = myAnalogRead ;
return TRUE ; return true ;
} }

View File

@@ -28,6 +28,7 @@
#include <stdio.h> #include <stdio.h>
#include <unistd.h> #include <unistd.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@@ -117,7 +118,7 @@ int mcp3422Setup (int pinBase, int i2cAddress, int sampleRate, int gain)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) if ((fd = wiringPiI2CSetup (i2cAddress)) < 0)
return FALSE ; return false ;
node = wiringPiNewNode (pinBase, 4) ; node = wiringPiNewNode (pinBase, 4) ;
@@ -126,5 +127,5 @@ int mcp3422Setup (int pinBase, int i2cAddress, int sampleRate, int gain)
node->data1 = gain ; node->data1 = gain ;
node->analogRead = myAnalogRead ; node->analogRead = myAnalogRead ;
return TRUE ; return true ;
} }

View File

@@ -22,6 +22,8 @@
*********************************************************************** ***********************************************************************
*/ */
#include <stdbool.h>
#include <wiringPi.h> #include <wiringPi.h>
#include <wiringPiSPI.h> #include <wiringPiSPI.h>
@@ -65,12 +67,12 @@ int mcp4802Setup (const int pinBase, int spiChannel)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if (wiringPiSPISetup (spiChannel, 1000000) < 0) if (wiringPiSPISetup (spiChannel, 1000000) < 0)
return FALSE ; return false ;
node = wiringPiNewNode (pinBase, 2) ; node = wiringPiNewNode (pinBase, 2) ;
node->fd = spiChannel ; node->fd = spiChannel ;
node->analogWrite = myAnalogWrite ; node->analogWrite = myAnalogWrite ;
return TRUE ; return true ;
} }

View File

@@ -23,6 +23,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <pthread.h> #include <pthread.h>
#include "wiringPi.h" #include "wiringPi.h"
@@ -113,7 +114,7 @@ int pcf8574Setup (const int pinBase, const int i2cAddress)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) if ((fd = wiringPiI2CSetup (i2cAddress)) < 0)
return FALSE ; return false ;
node = wiringPiNewNode (pinBase, 8) ; node = wiringPiNewNode (pinBase, 8) ;
@@ -123,5 +124,5 @@ int pcf8574Setup (const int pinBase, const int i2cAddress)
node->digitalWrite = myDigitalWrite ; node->digitalWrite = myDigitalWrite ;
node->data2 = wiringPiI2CRead (fd) ; node->data2 = wiringPiI2CRead (fd) ;
return TRUE ; return true ;
} }

View File

@@ -24,6 +24,7 @@
*/ */
#include <unistd.h> #include <unistd.h>
#include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include "wiringPi.h" #include "wiringPi.h"
@@ -82,7 +83,7 @@ int pcf8591Setup (const int pinBase, const int i2cAddress)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if ((fd = wiringPiI2CSetup (i2cAddress)) < 0) if ((fd = wiringPiI2CSetup (i2cAddress)) < 0)
return FALSE ; return false ;
node = wiringPiNewNode (pinBase, 4) ; node = wiringPiNewNode (pinBase, 4) ;
@@ -90,5 +91,5 @@ int pcf8591Setup (const int pinBase, const int i2cAddress)
node->analogRead = myAnalogRead ; node->analogRead = myAnalogRead ;
node->analogWrite = myAnalogWrite ; node->analogWrite = myAnalogWrite ;
return TRUE ; return true ;
} }

View File

@@ -41,6 +41,7 @@
#include <sys/mman.h> #include <sys/mman.h>
#include <fcntl.h> #include <fcntl.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
@@ -80,24 +81,24 @@ int pseudoPinsSetup(const int pinBase)
node = wiringPiNewNode(pinBase, PSEUDO_PINS); node = wiringPiNewNode(pinBase, PSEUDO_PINS);
if (node == NULL) { if (node == NULL) {
fprintf(stderr, "Error creating new wiringPi node"); fprintf(stderr, "Error creating new wiringPi node");
return FALSE; return false;
} }
node->fd = shm_open(SHARED_NAME, O_CREAT | O_RDWR, 0666); node->fd = shm_open(SHARED_NAME, O_CREAT | O_RDWR, 0666);
if (node->fd < 0) { if (node->fd < 0) {
perror("Error opening shared memory"); perror("Error opening shared memory");
return FALSE; return false;
} }
if (ftruncate(node->fd, PSEUDO_PINS * sizeof(int)) < 0) { if (ftruncate(node->fd, PSEUDO_PINS * sizeof(int)) < 0) {
perror("Error resizing shared memory"); perror("Error resizing shared memory");
return FALSE; return false;
} }
ptr = mmap(NULL, PSEUDO_PINS * sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, node->fd, 0); ptr = mmap(NULL, PSEUDO_PINS * sizeof(int), PROT_READ | PROT_WRITE, MAP_SHARED, node->fd, 0);
if (ptr == MAP_FAILED) { if (ptr == MAP_FAILED) {
perror("Error mapping shared memory"); perror("Error mapping shared memory");
return FALSE; return false;
} }
node->data0 = (unsigned int)(uintptr_t)ptr; node->data0 = (unsigned int)(uintptr_t)ptr;
@@ -105,5 +106,5 @@ int pseudoPinsSetup(const int pinBase)
node->analogRead = myAnalogRead; node->analogRead = myAnalogRead;
node->analogWrite = myAnalogWrite; node->analogWrite = myAnalogWrite;
return TRUE; return true;
} }

View File

@@ -25,6 +25,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <stdio.h> #include <stdio.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <time.h> #include <time.h>
#include "wiringPi.h" #include "wiringPi.h"
@@ -51,7 +52,7 @@ static int maxDetectLowHighWait (const int pin)
{ {
gettimeofday (&now, NULL) ; gettimeofday (&now, NULL) ;
if (timercmp (&now, &timeUp, >)) if (timercmp (&now, &timeUp, >))
return FALSE ; return false ;
} }
// Wait for it to go HIGH // Wait for it to go HIGH
@@ -65,10 +66,10 @@ static int maxDetectLowHighWait (const int pin)
{ {
gettimeofday (&now, NULL) ; gettimeofday (&now, NULL) ;
if (timercmp (&now, &timeUp, >)) if (timercmp (&now, &timeUp, >))
return FALSE ; return false ;
} }
return TRUE ; return true ;
} }
@@ -103,7 +104,7 @@ static unsigned int maxDetectClockByte (const int pin)
/* /*
* maxDetectRead: * maxDetectRead:
* Read in and return the 4 data bytes from the MaxDetect sensor. * Read in and return the 4 data bytes from the MaxDetect sensor.
* Return TRUE/FALSE depending on the checksum validity * Return true/false depending on the checksum validity
********************************************************************************* *********************************************************************************
*/ */
@@ -129,7 +130,7 @@ static int maxDetectRead (const int pin, unsigned char buffer [4])
// Now wait for sensor to pull pin low // Now wait for sensor to pull pin low
if (!maxDetectLowHighWait (pin)) if (!maxDetectLowHighWait (pin))
return FALSE ; return false ;
// and read in 5 bytes (40 bits) // and read in 5 bytes (40 bits)
@@ -158,7 +159,7 @@ static int maxDetectRead (const int pin, unsigned char buffer [4])
// reading is probably bogus. // reading is probably bogus.
if ((took.tv_sec != 0) || (took.tv_usec > 16000)) if ((took.tv_sec != 0) || (took.tv_usec > 16000))
return FALSE ; return false ;
return checksum == localBuf [4] ; return checksum == localBuf [4] ;
} }
@@ -181,7 +182,7 @@ static int myReadRHT03 (const int pin, int *temp, int *rh)
result = maxDetectRead (pin, buffer) ; result = maxDetectRead (pin, buffer) ;
if (!result) if (!result)
return FALSE ; return false ;
*rh = (buffer [0] * 256 + buffer [1]) ; *rh = (buffer [0] * 256 + buffer [1]) ;
*temp = (buffer [2] * 256 + buffer [3]) ; *temp = (buffer [2] * 256 + buffer [3]) ;
@@ -196,9 +197,9 @@ static int myReadRHT03 (const int pin, int *temp, int *rh)
// (which does seem to happen - no realtime here) // (which does seem to happen - no realtime here)
if ((*rh > 999) || (*temp > 800) || (*temp < -400)) if ((*rh > 999) || (*temp > 800) || (*temp < -400))
return FALSE ; return false ;
return TRUE ; return true ;
} }
@@ -239,7 +240,7 @@ int rht03Setup (const int pinBase, const int piPin)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if ((piPin & PI_GPIO_MASK) != 0) // Must be an on-board pin if ((piPin & PI_GPIO_MASK) != 0) // Must be an on-board pin
return FALSE ; return false ;
// 2 pins - temperature and humidity // 2 pins - temperature and humidity
@@ -248,5 +249,5 @@ int rht03Setup (const int pinBase, const int piPin)
node->fd = piPin ; node->fd = piPin ;
node->analogRead = myAnalogRead ; node->analogRead = myAnalogRead ;
return TRUE ; return true ;
} }

View File

@@ -22,6 +22,8 @@
*********************************************************************** ***********************************************************************
*/ */
#include <stdbool.h>
#include <wiringPi.h> #include <wiringPi.h>
#include <wiringPiI2C.h> #include <wiringPiI2C.h>
@@ -55,7 +57,7 @@ int sn3218Setup (const int pinBase)
struct wiringPiNodeStruct *node ; struct wiringPiNodeStruct *node ;
if ((fd = wiringPiI2CSetup (0x54)) < 0) if ((fd = wiringPiI2CSetup (0x54)) < 0)
return FALSE ; return false ;
// Setup the chip - initialise all 18 LEDs to off // Setup the chip - initialise all 18 LEDs to off
@@ -71,5 +73,5 @@ int sn3218Setup (const int pinBase)
node->fd = fd ; node->fd = fd ;
node->analogWrite = myAnalogWrite ; node->analogWrite = myAnalogWrite ;
return TRUE ; return true ;
} }

View File

@@ -29,6 +29,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include "wiringPi.h" #include "wiringPi.h"
@@ -105,5 +106,5 @@ int sr595Setup (const int pinBase, const int numPins,
pinMode (clockPin, OUTPUT) ; pinMode (clockPin, OUTPUT) ;
pinMode (latchPin, OUTPUT) ; pinMode (latchPin, OUTPUT) ;
return TRUE ; return true ;
} }

View File

@@ -83,7 +83,8 @@ int main (void) {
case PI_MODEL_400: case PI_MODEL_400:
case PI_MODEL_CM4: case PI_MODEL_CM4:
case PI_MODEL_CM4S: case PI_MODEL_CM4S:
fExpectTimedigitalWrite = 0.020; //us //fExpectTimedigitalWrite = 0.020; //us - with kernel <6.12.47
fExpectTimedigitalWrite = 0.016; //us
fExpectTimedigitalRead = 0.038; //us fExpectTimedigitalRead = 0.038; //us
fExpectTimepinMode = 0.121; //us fExpectTimepinMode = 0.121; //us
fWriteReadDelayFactor = 1.86; fWriteReadDelayFactor = 1.86;

View File

@@ -77,15 +77,18 @@ int main (void) {
int Pi5 = 0; int Pi5 = 0;
double MaxFreq = 100.0; double MaxFreq = 100.0;
switch(RaspberryPiModel) { switch(RaspberryPiModel) {
case PI_MODEL_A: case PI_MODEL_A:
case PI_MODEL_B: case PI_MODEL_B:
case PI_MODEL_BP: case PI_MODEL_BP:
case PI_MODEL_AP: case PI_MODEL_AP:
case PI_MODEL_CM:
MaxFreq = 5.0; // 4.8 kHz -> ~26% CPU@800 MHz
printf(" - Pi1/BCM2835 detected, will skip tests with frequency above %g kHz\n", MaxFreq);
break;
case PI_MODEL_ZERO: case PI_MODEL_ZERO:
case PI_MODEL_ZERO_W: case PI_MODEL_ZERO_W:
case PI_MODEL_CM: MaxFreq = 13.0; // 12.5 kHz -> ~42% CPU@1000 MHz
MaxFreq = 13.0; // 12.5 kHz -> ~40% CPU@800 MHz printf(" - PiZero/BCM2835 detected, will skip tests with frequency above %g kHz\n", MaxFreq);
printf(" - Pi1/BCM2835 detected, will skip tests with frequency above %g kHz\n", MaxFreq);
break; break;
case PI_MODEL_2: case PI_MODEL_2:
MaxFreq = 20.0; MaxFreq = 20.0;

View File

@@ -1,15 +1,14 @@
// WiringPi test program: SPI functions (need XO hardware) // WiringPi test program: SPI functions (need XO hardware)
// Compile: gcc -Wall wiringpi_xotest_test1_spi.c -o wiringpi_xotest_test1_spi -lwiringPi // Compile: gcc -Wall wiringpi_xotest_test1_spi.c -o wiringpi_xotest_test1_spi -lwiringPi
#include <unistd.h> #include <unistd.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <signal.h> #include <signal.h>
#include <time.h> #include <time.h>
#include "wpi_test.h" #include "wpi_test.h"
#include <wiringPiSPI.h> #include <wiringPiSPI.h>
#define TRUE (1==1)
#define FALSE (!TRUE)
#define CHAN_CONFIG_SINGLE 8 #define CHAN_CONFIG_SINGLE 8
#define CHAN_CONFIG_DIFF 0 #define CHAN_CONFIG_DIFF 0
@@ -66,17 +65,19 @@ int main(int argc, char *argv []){
wiringPiSetup(); wiringPiSetup();
if ((hSPI = wiringPiSPISetup (spiChannel, spiSpeed)) < 0) { printf("wiringPiSPISetup (spiChannel=%d, spiSpeed=%d)\n",spiChannel, spiSpeed);
if ((hSPI = wiringPiSPISetup(spiChannel, spiSpeed)) < 0) {
FailAndExitWithErrno("wiringPiSPISetup", hSPI); FailAndExitWithErrno("wiringPiSPISetup", hSPI);
} }
int hSPIOld=hSPI; int hSPIOld=hSPI;
//printf("\nSPI fd = %d\n call close now\n", hSPI); printf("wiringPiSPIClose(spiChannel=%d)\n",spiChannel);
int ret = wiringPiSPIClose(spiChannel); int ret = wiringPiSPIClose(spiChannel);
if (ret!=0) { if (ret!=0) {
FailAndExitWithErrno("wiringPiSPIClose", ret); FailAndExitWithErrno("wiringPiSPIClose", ret);
} }
printf("wiringPiSPIxSetupMode(0, spiChannel=%d, spiSpeed=%d, 0)\n",spiChannel, spiSpeed);
if ((hSPI = wiringPiSPIxSetupMode(0, spiChannel, spiSpeed, 0)) < 0) { if ((hSPI = wiringPiSPIxSetupMode(0, spiChannel, spiSpeed, 0)) < 0) {
FailAndExitWithErrno("wiringPiSPIxSetup", hSPI); FailAndExitWithErrno("wiringPiSPIxSetup", hSPI);
} }
@@ -151,12 +152,18 @@ int main(int argc, char *argv []){
digitalWriteEx(24, GPIOIn, HIGH); digitalWriteEx(24, GPIOIn, HIGH);
checkVoltage(3.3f, "Analog value 6xHigh"); checkVoltage(3.3f, "Analog value 6xHigh");
CH1 = AnalogRead(3, 1, &returnvalue);
CheckSame("\nReading Wrong channel 3 result ", CH1, 0); int unsupportedSPICh = 5;
CheckSame("\nReading Wrong channel 3 ioctl result ", returnvalue, -EINVAL); printf("\nCheck error for unsupported channel %d\n", unsupportedSPICh);
CH1 = AnalogRead(2, 1, &returnvalue); CH1 = AnalogRead(unsupportedSPICh, 1, &returnvalue);
CheckSame("\nReading Wrong channel 2 result ", CH1, 0); CheckSame("\nReading unsupported channel result ", CH1, 0);
CheckSame("\nReading Wrong channel 3 ioctl result ", returnvalue, -EBADF); CheckSame("Reading unsupported channel ioctl result ", returnvalue, -EINVAL);
int uninitSPICh = 2;
printf("\nCheck error for uninitialized channel %d\n", uninitSPICh);
CH1 = AnalogRead(uninitSPICh, 1, &returnvalue);
CheckSame("\nReading uninitialized channel result ", CH1, 0);
CheckSame("Reading uninitialized channel ioctl result ", returnvalue, -EBADF);
pinMode(22, INPUT); pinMode(22, INPUT);
pinMode(21, INPUT); pinMode(21, INPUT);
@@ -165,6 +172,7 @@ int main(int argc, char *argv []){
pinMode(27, INPUT); pinMode(27, INPUT);
pinMode(28, INPUT); pinMode(28, INPUT);
printf("\nwiringPiSPIxClose(0, spiChannel=%d)\n",spiChannel);
ret = wiringPiSPIxClose(0, spiChannel); ret = wiringPiSPIxClose(0, spiChannel);
CheckSame("wiringPiSPIxClose result", ret, 0); CheckSame("wiringPiSPIxClose result", ret, 0);
if (ret!=0) { if (ret!=0) {
@@ -175,4 +183,3 @@ int main(int argc, char *argv []){
return UnitTestState(); return UnitTestState();
} }

View File

@@ -1,7 +1,7 @@
/* /*
* wiringPi: * wiringPi:
* Arduino look-a-like Wiring library for the Raspberry Pi * Arduino look-a-like Wiring library for the Raspberry Pi
* Copyright (c) 2012-2025 Gordon Henderson and contributors * Copyright (c) 20122019 Gordon Henderson; 20192026 Contributors
* Additional code for pwmSetClock by Chris Hall <chris@kchall.plus.com> * Additional code for pwmSetClock by Chris Hall <chris@kchall.plus.com>
* *
* Thanks to code samples from Gert Jan van Loo and the * Thanks to code samples from Gert Jan van Loo and the
@@ -55,6 +55,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h> #include <stdbool.h>
#include <ctype.h> #include <ctype.h>
@@ -251,8 +252,8 @@ static volatile unsigned int GPIO_RIO ;
#define PAGE_SIZE (4*1024) #define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024) #define BLOCK_SIZE (4*1024)
static unsigned int usingGpioMem = FALSE ; static unsigned int usingGpioMem = false ;
static int wiringPiSetuped = FALSE ; static int wiringPiSetuped = false ;
// PWM // PWM
// Word offsets into the PWM control region // Word offsets into the PWM control region
@@ -447,12 +448,12 @@ static int RaspberryPiLayout = -1;
// Debugging & Return codes // Debugging & Return codes
int wiringPiDebug = FALSE ; int wiringPiDebug = false ;
int wiringPiReturnCodes = FALSE ; int wiringPiReturnCodes = false ;
// Use /dev/gpiomem ? // Use /dev/gpiomem ?
int wiringPiTryGpioMem = FALSE ; int wiringPiTryGpioMem = false ;
enum WPIFlag { enum WPIFlag {
WPI_FLAG_INPUT = 0x04, WPI_FLAG_INPUT = 0x04,
@@ -1688,7 +1689,7 @@ struct wiringPiNodeStruct *wiringPiNewNode (int pinBase, int numPins)
if (wiringPiFindNode (pin) != NULL) if (wiringPiFindNode (pin) != NULL)
(void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Pin %d overlaps with existing definition\n", pin) ; (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Pin %d overlaps with existing definition\n", pin) ;
node = (struct wiringPiNodeStruct *)calloc (sizeof (struct wiringPiNodeStruct), 1) ; // calloc zeros node = (struct wiringPiNodeStruct *)calloc(1, sizeof (struct wiringPiNodeStruct)); // calloc zeros
if (node == NULL) if (node == NULL)
(void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Unable to allocate memory: %s\n", strerror (errno)) ; (void)wiringPiFailure (WPI_FATAL, "wiringPiNewNode: Unable to allocate memory: %s\n", strerror (errno)) ;
@@ -2299,10 +2300,10 @@ int digitalRead (int pin)
} }
if (ISRP1MODEL) { if (ISRP1MODEL) {
switch(gpio[2*pin] & RP1_STATUS_LEVEL_MASK) { if ((gpio[2*pin] & RP1_STATUS_LEVEL_MASK) == RP1_STATUS_LEVEL_HIGH) {
default: // 11 or 00 not allowed, give LOW! return HIGH;
case RP1_STATUS_LEVEL_LOW: return LOW ; } else { // 11 or 00 not allowed, give LOW!
case RP1_STATUS_LEVEL_HIGH: return HIGH ; return LOW;
} }
} else { } else {
if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0) if ((*(gpio + gpioToGPLEV [pin]) & (1 << (pin & 31))) != 0)
@@ -2867,42 +2868,32 @@ int waitForInterruptClose(int pin) {
} }
/* /*
* interruptHandlerV2: * interruptHandlerInit:
* This is a thread and gets started to wait for the interrupt we're * Initializes an interrupt handler before starting the listener loop in a
* hoping to catch. It will call the user-function when the interrupt * separate thread.
* fires. * Returns: >0 on successful initialization, 0 if the listener loop does not
* have to start, -1 on error.
********************************************************************************* *********************************************************************************
*/ */
void *interruptHandlerV2(void *arg) static int interruptHandlerInit(int pin, int EdgeMode, unsigned long debounce_period_us)
{ {
const char* strmode = ""; const char* strmode = "";
int pin, EdgeMode, ret, fd, attr, i; int ret, attr;
unsigned int readret;
unsigned long debounce_period_us;
struct pollfd polls ;
struct gpio_v2_line_config config; struct gpio_v2_line_config config;
struct gpio_v2_line_request req; struct gpio_v2_line_request req;
struct gpio_v2_line_event evdat[64];
struct WPIWfiStatus wfiStatus;
struct timespec tspec = {0, 5e5}; /* 0.5 ms timeout {0, 1e6} */
pin = *(int *)arg;
if (wiringPiGpioDeviceGetFd()<0) { if (wiringPiGpioDeviceGetFd() < 0) {
return NULL; return -1;
} }
EdgeMode = isrEdgeMode[pin];
debounce_period_us = isrDebouncePeriodUs[pin];
if (wiringPiDebug) { if (wiringPiDebug) {
printf ("interruptHandlerV2: GPIO line %d, edge mode %d, debounce_period_us %lu \n", pin, EdgeMode, debounce_period_us) ; printf ("interruptHandlerV2: GPIO line %d, edge mode %d, debounce_period_us %lu \n", pin, EdgeMode, debounce_period_us) ;
} }
memset(&req, 0, sizeof(req)); memset(&req, 0, sizeof(req));
memset(&config, 0, sizeof(config)); memset(&config, 0, sizeof(config));
/* setup config */ /* setup config */
config.flags = GPIO_V2_LINE_FLAG_INPUT; config.flags = GPIO_V2_LINE_FLAG_INPUT;
switch(EdgeMode) { switch(EdgeMode) {
@@ -2911,7 +2902,7 @@ void *interruptHandlerV2(void *arg)
if (wiringPiDebug) { if (wiringPiDebug) {
printf ("interruptHandlerV2: waitForInterruptMode edge mode INT_EDGE_SETUP - exiting\n") ; printf ("interruptHandlerV2: waitForInterruptMode edge mode INT_EDGE_SETUP - exiting\n") ;
} }
return NULL; return 0;
case INT_EDGE_FALLING: case INT_EDGE_FALLING:
config.flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING; config.flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING;
strmode = "falling"; strmode = "falling";
@@ -2926,7 +2917,7 @@ void *interruptHandlerV2(void *arg)
break; break;
} }
strcpy(req.consumer, "wiringpi_gpio_irq"); strcpy(req.consumer, "wiringpi_gpio_irq");
if (debounce_period_us) { if (debounce_period_us) {
attr = config.num_attrs; attr = config.num_attrs;
config.num_attrs++; config.num_attrs++;
@@ -2934,7 +2925,7 @@ void *interruptHandlerV2(void *arg)
config.attrs[attr].attr.id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE; config.attrs[attr].attr.id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE;
config.attrs[attr].attr.debounce_period_us = debounce_period_us; config.attrs[attr].attr.debounce_period_us = debounce_period_us;
} }
req.num_lines = 1; req.num_lines = 1;
req.event_buffer_size = 45; req.event_buffer_size = 45;
req.offsets[0] = pin; req.offsets[0] = pin;
@@ -2943,16 +2934,46 @@ void *interruptHandlerV2(void *arg)
ret = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req); ret = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req);
if (ret == -1) { if (ret == -1) {
ReportDeviceError("interruptHandlerV2: get line event", pin , strmode, ret); ReportDeviceError("interruptHandlerV2: get line event", pin , strmode, ret);
return NULL; return -1;
} }
if (wiringPiDebug) if (wiringPiDebug) {
printf ("interruptHandlerV2: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ; printf ("interruptHandlerV2: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd);
}
return req.fd;
}
struct interrupt_handler_params {
int pin;
int fd;
};
/*
* interruptHandlerV2:
* This is a thread and gets started to wait for the interrupt we're
* hoping to catch. It will call the user-function when the interrupt
* fires.
*********************************************************************************
*/
static void *interruptHandlerV2(void *arg)
{
struct interrupt_handler_params *params;
int pin, ret, fd, i;
unsigned int readret;
struct pollfd polls ;
struct gpio_v2_line_event evdat[64];
struct WPIWfiStatus wfiStatus;
struct timespec tspec = {0, 5e5}; /* 0.5 ms timeout {0, 1e6} */
params = (struct interrupt_handler_params *)arg;
pin = params->pin;
fd = params->fd;
/* set event fd */ /* set event fd */
fd = req.fd;
isrFds [pin] = fd; isrFds [pin] = fd;
(void)piHiPri (55) ; // Only effective if we run as root (void)piHiPri (55) ; // Only effective if we run as root
for (;;) { // check if event data is available, check if interruptHandlerV2 thread must be canceled for (;;) { // check if event data is available, check if interruptHandlerV2 thread must be canceled
@@ -2961,24 +2982,24 @@ void *interruptHandlerV2(void *arg)
polls.fd = fd; polls.fd = fd;
polls.events = POLLIN | POLLPRI; polls.events = POLLIN | POLLPRI;
polls.revents = 0; polls.revents = 0;
// get event data, this is also a cancelation point, when pthread_cancel is called // get event data, this is also a cancelation point, when pthread_cancel is called
ret = ppoll(&polls, 1, &tspec, NULL); // returns -1 on error, 0 on timeout, >0 number of elements ret = ppoll(&polls, 1, &tspec, NULL); // returns -1 on error, 0 on timeout, >0 number of elements
if (ret < 0) { // we do not reach this point if canceled, ppoll does not return, is Cancellation Point if (ret < 0) { // we do not reach this point if canceled, ppoll does not return, is Cancellation Point
if (wiringPiDebug) if (wiringPiDebug)
printf("interruptHandlerV2: ERROR: poll returned=%d\n", ret); printf("interruptHandlerV2: ERROR: poll returned=%d\n", ret);
pthread_exit(NULL); pthread_exit(NULL);
return NULL; // never landing here return NULL; // never landing here
} else if (ret == 0) { } else if (ret == 0) {
// if (wiringPiDebug) // if (wiringPiDebug)
// printf("interruptHandlerV2: timeout: poll returned=%d\n", ret); // printf("interruptHandlerV2: timeout: poll returned=%d\n", ret);
continue; continue;
} }
else { else {
if (wiringPiDebug) if (wiringPiDebug)
printf ("interruptHandlerV2: IRQ line %d received %d events, fd=%d\n", pin, ret, isrFds[pin]) ; printf ("interruptHandlerV2: IRQ line %d received %d events, fd=%d\n", pin, ret, isrFds[pin]) ;
if (polls.revents & POLLIN) { if (polls.revents & POLLIN) {
/* read event data */ /* read event data */
readret = read(fd, &evdat, sizeof(evdat)); readret = read(fd, &evdat, sizeof(evdat));
if (readret >= sizeof(evdat[0])) { if (readret >= sizeof(evdat[0])) {
@@ -2988,7 +3009,7 @@ void *interruptHandlerV2(void *arg)
ret = readret/sizeof(evdat[0]); // number of events read from fd ret = readret/sizeof(evdat[0]); // number of events read from fd
for (i = 0; i < ret; ++i) { for (i = 0; i < ret; ++i) {
if (isrFunctionsV2[pin]) { if (isrFunctionsV2[pin]) {
if (wiringPiDebug) if (wiringPiDebug)
printf( "interruptHandlerV2: GPIO EVENT at %llu on line %u (%u|%u) \n", evdat[i].timestamp_ns, evdat[i].offset, evdat[i].line_seqno, evdat[i].seqno); printf( "interruptHandlerV2: GPIO EVENT at %llu on line %u (%u|%u) \n", evdat[i].timestamp_ns, evdat[i].offset, evdat[i].line_seqno, evdat[i].seqno);
wfiStatus.statusOK = 1; wfiStatus.statusOK = 1;
wfiStatus.pinBCM = pin; wfiStatus.pinBCM = pin;
@@ -3005,10 +3026,10 @@ void *interruptHandlerV2(void *arg)
break; break;
default: default:
wfiStatus.edge = INT_EDGE_SETUP; // edge = 0 wfiStatus.edge = INT_EDGE_SETUP; // edge = 0
if (wiringPiDebug) if (wiringPiDebug)
printf("waitForInterrupt2: unknown event\n"); printf("waitForInterrupt2: unknown event\n");
break; break;
} }
wfiStatus.timeStamp_us = evdat[i].timestamp_ns/1000LL; wfiStatus.timeStamp_us = evdat[i].timestamp_ns/1000LL;
if (wiringPiDebug) { if (wiringPiDebug) {
printf( "interruptHandlerV2: call isr function\n"); printf( "interruptHandlerV2: call isr function\n");
@@ -3032,7 +3053,7 @@ void *interruptHandlerV2(void *arg)
else { // if thread canceled we do not reach this point, read(...) does not return, is Cancellation Point else { // if thread canceled we do not reach this point, read(...) does not return, is Cancellation Point
if (wiringPiDebug) if (wiringPiDebug)
printf ("interruptHandlerV2: reading events from fd received signal, exit thread\n"); printf ("interruptHandlerV2: reading events from fd received signal, exit thread\n");
pthread_exit(NULL); pthread_exit(NULL);
return NULL; // never landing here return NULL; // never landing here
} }
} }
@@ -3040,9 +3061,8 @@ void *interruptHandlerV2(void *arg)
} }
} }
/* /*
* wiringPiISR: * wiringPiISRInternal:
* Pi Specific. * Pi Specific.
* Take the details and create an interrupt handler that will do a call- * Take the details and create an interrupt handler that will do a call-
* back to the user supplied function. * back to the user supplied function.
@@ -3063,38 +3083,48 @@ int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiSta
printf("wiringPi: wiringPiISR pin %d, edgeMode %d\n", pin, edgeMode); printf("wiringPi: wiringPiISR pin %d, edgeMode %d\n", pin, edgeMode);
} }
if (isrFunctions[pin] || isrFunctionsV2[pin]) { if (isrFunctions[pin] || isrFunctionsV2[pin]) {
fprintf(stderr, "wiringPi: ISR function already active, ignoring \n"); fprintf(stderr, "wiringPi: ISR function already active\n");
} }
isrFunctionsV2[pin] = function;
isrUserdata[pin] = userdata;
isrFunctions[pin] = functionClassic;
isrEdgeMode[pin] = edgeMode;
isrDebouncePeriodUs[pin] = debounce_period_us;
if (wiringPiDebug) { if (wiringPiDebug) {
printf("wiringPi: mutex in\n"); printf("wiringPi: mutex in\n");
} }
pthread_mutex_lock (&pinMutex) ; pthread_mutex_lock (&pinMutex) ;
pinPass = pin ; struct interrupt_handler_params params = {
if (wiringPiDebug) { .pin = pin,
printf("wiringPi: pthread_create before 0x%lX\n", (unsigned long)isrThreads[pin]); };
params.fd = interruptHandlerInit(pin, edgeMode, debounce_period_us);
if (params.fd < 0) {
pthread_mutex_unlock (&pinMutex) ;
return -1;
} }
if (pthread_create (&isrThreads[pin], NULL, interruptHandlerV2, &pin)==0) {
// OK to start the new ISR. Update the table.
isrFunctionsV2[pin] = function;
isrUserdata[pin] = userdata;
isrFunctions[pin] = functionClassic;
isrEdgeMode[pin] = edgeMode;
isrDebouncePeriodUs[pin] = debounce_period_us;
pinPass = pin ;
if (params.fd > 0) {
if (wiringPiDebug) { if (wiringPiDebug) {
printf("wiringPi: pthread_create successed, 0x%lX\n", (unsigned long)isrThreads[pin]); printf("wiringPi: pthread_create before 0x%lX\n", (unsigned long)isrThreads[pin]);
} }
/* while (pinPass != -1) if (pthread_create (&isrThreads[pin], NULL, interruptHandlerV2, &params)==0) {
delay (1) ; */ if (wiringPiDebug) {
// wait so that interruptHandler is up und running. printf("wiringPi: pthread_create successed, 0x%lX\n", (unsigned long)isrThreads[pin]);
// when interruptHandler is running, the calling function wiringPiISR }
// must be still alive, otherwise the thread argument &pin points into nirwana, } else {
// when it is picked up from interruptHandler. if (wiringPiDebug) {
delay (10); printf("wiringPi: pthread_create failed\n");
} else { }
if (wiringPiDebug) {
printf("wiringPi: pthread_create failed\n");
} }
// wait so that interruptHandler is up und running.
// when interruptHandler is running, the calling function wiringPiISRInternal
// must be still alive, otherwise the thread argument &param points into nirwana,
// when it is picked up from interruptHandlerV2.
delay(10);
} }
if (wiringPiDebug) { if (wiringPiDebug) {
@@ -3326,8 +3356,7 @@ int CheckPCIeFileContent(const char* pcieaddress, const char* filename, const ch
} }
void GetRP1Memory() { void GetRP1Memory(void) {
pciemem_RP1[0] = '\0'; pciemem_RP1[0] = '\0';
DIR *dir = opendir(pcie_path); DIR *dir = opendir(pcie_path);
struct dirent *entry; struct dirent *entry;
@@ -3360,7 +3389,7 @@ int wiringPiGlobalMemoryAccess(void)
piBoard(); piBoard();
if (piRP1Model()) { if (piRP1Model()) {
GetRP1Memory(pciemem_RP1, sizeof(pciemem_RP1)); GetRP1Memory();
gpiomemGlobal = pciemem_RP1; gpiomemGlobal = pciemem_RP1;
MMAP_size = pciemem_RP1_Size; MMAP_size = pciemem_RP1_Size;
BaseAddr = 0x00000000; BaseAddr = 0x00000000;
@@ -3423,13 +3452,13 @@ int wiringPiSetup (void)
if (wiringPiSetuped) if (wiringPiSetuped)
return 0 ; return 0 ;
wiringPiSetuped = TRUE ; wiringPiSetuped = true ;
if (getenv (ENV_DEBUG) != NULL) if (getenv (ENV_DEBUG) != NULL)
wiringPiDebug = TRUE ; wiringPiDebug = true ;
if (getenv (ENV_CODES) != NULL) if (getenv (ENV_CODES) != NULL)
wiringPiReturnCodes = TRUE ; wiringPiReturnCodes = true ;
if (wiringPiDebug) if (wiringPiDebug)
printf ("wiringPi: wiringPiSetup called\n") ; printf ("wiringPi: wiringPiSetup called\n") ;
@@ -3485,7 +3514,7 @@ int wiringPiSetup (void)
gpioToPwmPort[19] = 3; gpioToPwmPort[19] = 3;
} }
usingGpioMem = FALSE; usingGpioMem = false;
if (gpiomemGlobal==NULL || (fd = open (gpiomemGlobal, O_RDWR | O_SYNC | O_CLOEXEC)) < 0) if (gpiomemGlobal==NULL || (fd = open (gpiomemGlobal, O_RDWR | O_SYNC | O_CLOEXEC)) < 0)
{ {
if (wiringPiDebug) { if (wiringPiDebug) {
@@ -3494,7 +3523,7 @@ int wiringPiSetup (void)
if (gpiomemModule && (fd = open (gpiomemModule, O_RDWR | O_SYNC | O_CLOEXEC) ) >= 0) // We're using gpiomem if (gpiomemModule && (fd = open (gpiomemModule, O_RDWR | O_SYNC | O_CLOEXEC) ) >= 0) // We're using gpiomem
{ {
piGpioBase = 0 ; piGpioBase = 0 ;
usingGpioMem = TRUE ; usingGpioMem = true ;
} }
else else
return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open %s or %s: %s.\n" return wiringPiFailure (WPI_ALMOST, "wiringPiSetup: Unable to open %s or %s: %s.\n"
@@ -3678,15 +3707,15 @@ int wiringPiSetupGpioDevice (enum WPIPinType pinType) {
printf ("wiringPi: wiringPiSetupGpioDevice(%d) called\n", (int)pinType) ; printf ("wiringPi: wiringPiSetupGpioDevice(%d) called\n", (int)pinType) ;
} }
if (getenv (ENV_DEBUG) != NULL) if (getenv (ENV_DEBUG) != NULL)
wiringPiDebug = TRUE ; wiringPiDebug = true ;
if (getenv (ENV_CODES) != NULL) if (getenv (ENV_CODES) != NULL)
wiringPiReturnCodes = TRUE ; wiringPiReturnCodes = true ;
if (wiringPiGpioDeviceGetFd()<0) { if (wiringPiGpioDeviceGetFd()<0) {
return -1; return -1;
} }
wiringPiSetuped = TRUE ; wiringPiSetuped = true ;
if (piGpioLayout () == GPIO_LAYOUT_PI1_REV1){ if (piGpioLayout () == GPIO_LAYOUT_PI1_REV1){
pinToGpio = pinToGpioR1 ; pinToGpio = pinToGpioR1 ;
@@ -3709,7 +3738,7 @@ int wiringPiSetupGpioDevice (enum WPIPinType pinType) {
wiringPiMode = WPI_MODE_GPIO_DEVICE_PHYS; wiringPiMode = WPI_MODE_GPIO_DEVICE_PHYS;
break; break;
default: default:
wiringPiSetuped = FALSE; wiringPiSetuped = false;
return -1; return -1;
} }

View File

@@ -1,7 +1,7 @@
/* /*
* wiringPi.h: * wiringPi.h:
* Arduino like Wiring library for the Raspberry Pi. * Arduino like Wiring library for the Raspberry Pi.
* Copyright (c) 2012-2025 Gordon Henderson * Copyright (c) 20122019 Gordon Henderson; 20192026 Contributors
*********************************************************************** ***********************************************************************
* This file is part of wiringPi: * This file is part of wiringPi:
* https://github.com/WiringPi/WiringPi/ * https://github.com/WiringPi/WiringPi/
@@ -24,13 +24,14 @@
#ifndef __WIRING_PI_H__ #ifndef __WIRING_PI_H__
#define __WIRING_PI_H__ #define __WIRING_PI_H__
// C doesn't have true/false by default and I can never remember which #include <stdbool.h>
// way round they are, so ...
// (and yes, I know about stdbool.h but I like capitals for these and I'm old)
#ifndef TRUE // macros retained for old code compatibility, we now use stdbool.h
# define TRUE (1==1) #ifndef TRUE
# define FALSE (!TRUE) #define TRUE true
#endif
#ifndef FALSE
#define FALSE false
#endif #endif
// GCC warning suppressor // GCC warning suppressor

View File

@@ -1,7 +1,7 @@
/* /*
* wiringPiI2C.c: * wiringPiI2C.c:
* Simplified I2C access routines * Simplified I2C access routines
* Copyright (c) 2013-2024 Gordon Henderson and contributors * Copyright (c) 20132019 Gordon Henderson; 20192026 Contributors
*********************************************************************** ***********************************************************************
* This file is part of wiringPi: * This file is part of wiringPi:
* https://github.com/WiringPi/WiringPi/ * https://github.com/WiringPi/WiringPi/

View File

@@ -1,7 +1,7 @@
/* /*
* wiringPiI2C.h: * wiringPiI2C.h:
* Simplified I2C access routines * Simplified I2C access routines
* Copyright (c) 2013-2024 Gordon Henderson and contributors * Copyright (c) 20132019 Gordon Henderson; 20192026 Contributors
*********************************************************************** ***********************************************************************
* This file is part of wiringPi: * This file is part of wiringPi:
* https://github.com/WiringPi/WiringPi/ * https://github.com/WiringPi/WiringPi/

View File

@@ -1,7 +1,7 @@
/* /*
* wiringPiSPI.c: * wiringPiSPI.c:
* Simplified SPI access routines * Simplified SPI access routines
* Copyright (c) 2012-2025 Gordon Henderson and contributors * Copyright (c) 20122019 Gordon Henderson; 20192026 Contributors
*********************************************************************** ***********************************************************************
* This file is part of wiringPi: * This file is part of wiringPi:
* https://github.com/WiringPi/WiringPi/ * https://github.com/WiringPi/WiringPi/
@@ -44,9 +44,11 @@
//static const char *spiDev1 = "/dev/spidev0.1" ; //static const char *spiDev1 = "/dev/spidev0.1" ;
static const uint8_t spiBPW = 8 ; static const uint8_t spiBPW = 8 ;
static const uint16_t spiDelay = 0 ; static const uint16_t spiDelay = 0 ;
//https://datasheets.raspberrypi.com/cm4/cm4-datasheet.pdf //https://datasheets.raspberrypi.com/cm4/cm4-datasheet.pdf SPI0-6, CS0-2
//cm5-datasheet.pdf SPI0-5, CS depend on SPInumber, can be up to 4
//spi0-4cs.dts extention for supporting CS0-4
const uint8_t WPI_MaxSPINumbers = 7 ; const uint8_t WPI_MaxSPINumbers = 7 ;
const uint8_t WPI_MaxSPIChannels = 3 ; const uint8_t WPI_MaxSPIChannels = 5 ;
static uint32_t spiSpeeds [7][3] = static uint32_t spiSpeeds [7][3] =

View File

@@ -1,7 +1,7 @@
/* /*
* wiringPiSPI.h: * wiringPiSPI.h:
* Simplified SPI access routines * Simplified SPI access routines
* Copyright (c) 2012-2025 Gordon Henderson and contributors * Copyright (c) 20122019 Gordon Henderson; 20192026 Contributors
*********************************************************************** ***********************************************************************
* This file is part of wiringPi: * This file is part of wiringPi:
* https://github.com/WiringPi/WiringPi/ * https://github.com/WiringPi/WiringPi/

View File

@@ -27,6 +27,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdarg.h> #include <stdarg.h>
#include <ctype.h> #include <ctype.h>
@@ -146,7 +147,7 @@ static char *extractInt (char *progName, char *p, int *num)
static char *extractStr (char *progName, char *p, char **str) static char *extractStr (char *progName, char *p, char **str)
{ {
char *q, *r ; char *q, *r ;
int quoted = FALSE ; int quoted = false ;
if (*p != ':') if (*p != ':')
{ {
@@ -158,7 +159,7 @@ static char *extractStr (char *progName, char *p, char **str)
if (*p == '[') if (*p == '[')
{ {
quoted = TRUE ; quoted = true ;
++p ; ++p ;
} }
@@ -205,17 +206,17 @@ static int doExtensionMcp23008 (char *progName, int pinBase, char *params)
int i2c ; int i2c ;
if ((params = extractInt (progName, params, &i2c)) == NULL) if ((params = extractInt (progName, params, &i2c)) == NULL)
return FALSE ; return false ;
if ((i2c < 0x01) || (i2c > 0x77)) if ((i2c < 0x01) || (i2c > 0x77))
{ {
verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
return FALSE ; return false ;
} }
mcp23008Setup (pinBase, i2c) ; mcp23008Setup (pinBase, i2c) ;
return TRUE ; return true ;
} }
@@ -231,17 +232,17 @@ static int doExtensionMcp23016 (char *progName, int pinBase, char *params)
int i2c ; int i2c ;
if ((params = extractInt (progName, params, &i2c)) == NULL) if ((params = extractInt (progName, params, &i2c)) == NULL)
return FALSE ; return false ;
if ((i2c < 0x03) || (i2c > 0x77)) if ((i2c < 0x03) || (i2c > 0x77))
{ {
verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
return FALSE ; return false ;
} }
mcp23016Setup (pinBase, i2c) ; mcp23016Setup (pinBase, i2c) ;
return TRUE ; return true ;
} }
@@ -257,17 +258,17 @@ static int doExtensionMcp23017 (char *progName, int pinBase, char *params)
int i2c ; int i2c ;
if ((params = extractInt (progName, params, &i2c)) == NULL) if ((params = extractInt (progName, params, &i2c)) == NULL)
return FALSE ; return false ;
if ((i2c < 0x03) || (i2c > 0x77)) if ((i2c < 0x03) || (i2c > 0x77))
{ {
verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
return FALSE ; return false ;
} }
mcp23017Setup (pinBase, i2c) ; mcp23017Setup (pinBase, i2c) ;
return TRUE ; return true ;
} }
@@ -283,26 +284,26 @@ static int doExtensionMcp23s08 (char *progName, int pinBase, char *params)
int spi, port ; int spi, port ;
if ((params = extractInt (progName, params, &spi)) == NULL) if ((params = extractInt (progName, params, &spi)) == NULL)
return FALSE ; return false ;
if ((spi < 0) || (spi > 1)) if ((spi < 0) || (spi > 1))
{ {
verbError ("%s: SPI address (%d) out of range", progName, spi) ; verbError ("%s: SPI address (%d) out of range", progName, spi) ;
return FALSE ; return false ;
} }
if ((params = extractInt (progName, params, &port)) == NULL) if ((params = extractInt (progName, params, &port)) == NULL)
return FALSE ; return false ;
if ((port < 0) || (port > 7)) if ((port < 0) || (port > 7))
{ {
verbError ("%s: port address (%d) out of range", progName, port) ; verbError ("%s: port address (%d) out of range", progName, port) ;
return FALSE ; return false ;
} }
mcp23s08Setup (pinBase, spi, port) ; mcp23s08Setup (pinBase, spi, port) ;
return TRUE ; return true ;
} }
@@ -318,26 +319,26 @@ static int doExtensionMcp23s17 (char *progName, int pinBase, char *params)
int spi, port ; int spi, port ;
if ((params = extractInt (progName, params, &spi)) == NULL) if ((params = extractInt (progName, params, &spi)) == NULL)
return FALSE ; return false ;
if ((spi < 0) || (spi > 1)) if ((spi < 0) || (spi > 1))
{ {
verbError ("%s: SPI address (%d) out of range", progName, spi) ; verbError ("%s: SPI address (%d) out of range", progName, spi) ;
return FALSE ; return false ;
} }
if ((params = extractInt (progName, params, &port)) == NULL) if ((params = extractInt (progName, params, &port)) == NULL)
return FALSE ; return false ;
if ((port < 0) || (port > 7)) if ((port < 0) || (port > 7))
{ {
verbError ("%s: port address (%d) out of range", progName, port) ; verbError ("%s: port address (%d) out of range", progName, port) ;
return FALSE ; return false ;
} }
mcp23s17Setup (pinBase, spi, port) ; mcp23s17Setup (pinBase, spi, port) ;
return TRUE ; return true ;
} }
@@ -355,26 +356,26 @@ static int doExtensionSr595 (char *progName, int pinBase, char *params)
// Extract pins // Extract pins
if ((params = extractInt (progName, params, &pins)) == NULL) if ((params = extractInt (progName, params, &pins)) == NULL)
return FALSE ; return false ;
if ((pins < 8) || (pins > 32)) if ((pins < 8) || (pins > 32))
{ {
verbError ("%s: pin count (%d) out of range - 8-32 expected.", progName, pins) ; verbError ("%s: pin count (%d) out of range - 8-32 expected.", progName, pins) ;
return FALSE ; return false ;
} }
if ((params = extractInt (progName, params, &data)) == NULL) if ((params = extractInt (progName, params, &data)) == NULL)
return FALSE ; return false ;
if ((params = extractInt (progName, params, &clock)) == NULL) if ((params = extractInt (progName, params, &clock)) == NULL)
return FALSE ; return false ;
if ((params = extractInt (progName, params, &latch)) == NULL) if ((params = extractInt (progName, params, &latch)) == NULL)
return FALSE ; return false ;
sr595Setup (pinBase, pins, data, clock, latch) ; sr595Setup (pinBase, pins, data, clock, latch) ;
return TRUE ; return true ;
} }
@@ -390,17 +391,17 @@ static int doExtensionPcf8574 (char *progName, int pinBase, char *params)
int i2c ; int i2c ;
if ((params = extractInt (progName, params, &i2c)) == NULL) if ((params = extractInt (progName, params, &i2c)) == NULL)
return FALSE ; return false ;
if ((i2c < 0x03) || (i2c > 0x77)) if ((i2c < 0x03) || (i2c > 0x77))
{ {
verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
return FALSE ; return false ;
} }
pcf8574Setup (pinBase, i2c) ; pcf8574Setup (pinBase, i2c) ;
return TRUE ; return true ;
} }
@@ -416,17 +417,17 @@ static int doExtensionAds1115 (char *progName, int pinBase, char *params)
int i2c ; int i2c ;
if ((params = extractInt (progName, params, &i2c)) == NULL) if ((params = extractInt (progName, params, &i2c)) == NULL)
return FALSE ; return false ;
if ((i2c < 0x03) || (i2c > 0x77)) if ((i2c < 0x03) || (i2c > 0x77))
{ {
verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
return FALSE ; return false ;
} }
ads1115Setup (pinBase, i2c) ; ads1115Setup (pinBase, i2c) ;
return TRUE ; return true ;
} }
@@ -442,17 +443,17 @@ static int doExtensionPcf8591 (char *progName, int pinBase, char *params)
int i2c ; int i2c ;
if ((params = extractInt (progName, params, &i2c)) == NULL) if ((params = extractInt (progName, params, &i2c)) == NULL)
return FALSE ; return false ;
if ((i2c < 0x03) || (i2c > 0x77)) if ((i2c < 0x03) || (i2c > 0x77))
{ {
verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
return FALSE ; return false ;
} }
pcf8591Setup (pinBase, i2c) ; pcf8591Setup (pinBase, i2c) ;
return TRUE ; return true ;
} }
@@ -467,7 +468,7 @@ static int doExtensionPseudoPins (UNU char *progName, int pinBase, UNU char *par
{ {
pseudoPinsSetup (pinBase) ; pseudoPinsSetup (pinBase) ;
return TRUE ; return true ;
} }
@@ -482,7 +483,7 @@ static int doExtensionBmp180 (UNU char *progName, int pinBase, UNU char *params)
{ {
bmp180Setup (pinBase) ; bmp180Setup (pinBase) ;
return TRUE ; return true ;
} }
@@ -497,7 +498,7 @@ static int doExtensionHtu21d (UNU char *progName, int pinBase, UNU char *params)
{ {
htu21dSetup (pinBase) ; htu21dSetup (pinBase) ;
return TRUE ; return true ;
} }
@@ -513,7 +514,7 @@ static int doExtensionDs18b20 (char *progName, int pinBase, char *params)
char *serialNum ; char *serialNum ;
if ((params = extractStr (progName, params, &serialNum)) == NULL) if ((params = extractStr (progName, params, &serialNum)) == NULL)
return FALSE ; return false ;
return ds18b20Setup (pinBase, serialNum) ; return ds18b20Setup (pinBase, serialNum) ;
} }
@@ -531,7 +532,7 @@ static int doExtensionRht03 (char *progName, int pinBase, char *params)
int piPin ; int piPin ;
if ((params = extractInt (progName, params, &piPin)) == NULL) if ((params = extractInt (progName, params, &piPin)) == NULL)
return FALSE ; return false ;
return rht03Setup (pinBase, piPin) ; return rht03Setup (pinBase, piPin) ;
} }
@@ -549,17 +550,17 @@ static int doExtensionMax31855 (char *progName, int pinBase, char *params)
int spi ; int spi ;
if ((params = extractInt (progName, params, &spi)) == NULL) if ((params = extractInt (progName, params, &spi)) == NULL)
return FALSE ; return false ;
if ((spi < 0) || (spi > 1)) if ((spi < 0) || (spi > 1))
{ {
verbError ("%s: SPI channel (%d) out of range", progName, spi) ; verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
return FALSE ; return false ;
} }
max31855Setup (pinBase, spi) ; max31855Setup (pinBase, spi) ;
return TRUE ; return true ;
} }
@@ -575,17 +576,17 @@ static int doExtensionMcp3002 (char *progName, int pinBase, char *params)
int spi ; int spi ;
if ((params = extractInt (progName, params, &spi)) == NULL) if ((params = extractInt (progName, params, &spi)) == NULL)
return FALSE ; return false ;
if ((spi < 0) || (spi > 1)) if ((spi < 0) || (spi > 1))
{ {
verbError ("%s: SPI channel (%d) out of range", progName, spi) ; verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
return FALSE ; return false ;
} }
mcp3002Setup (pinBase, spi) ; mcp3002Setup (pinBase, spi) ;
return TRUE ; return true ;
} }
@@ -601,17 +602,17 @@ static int doExtensionMcp3004 (char *progName, int pinBase, char *params)
int spi ; int spi ;
if ((params = extractInt (progName, params, &spi)) == NULL) if ((params = extractInt (progName, params, &spi)) == NULL)
return FALSE ; return false ;
if ((spi < 0) || (spi > 1)) if ((spi < 0) || (spi > 1))
{ {
verbError ("%s: SPI channel (%d) out of range", progName, spi) ; verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
return FALSE ; return false ;
} }
mcp3004Setup (pinBase, spi) ; mcp3004Setup (pinBase, spi) ;
return TRUE ; return true ;
} }
@@ -627,17 +628,17 @@ static int doExtensionMax5322 (char *progName, int pinBase, char *params)
int spi ; int spi ;
if ((params = extractInt (progName, params, &spi)) == NULL) if ((params = extractInt (progName, params, &spi)) == NULL)
return FALSE ; return false ;
if ((spi < 0) || (spi > 1)) if ((spi < 0) || (spi > 1))
{ {
verbError ("%s: SPI channel (%d) out of range", progName, spi) ; verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
return FALSE ; return false ;
} }
max5322Setup (pinBase, spi) ; max5322Setup (pinBase, spi) ;
return TRUE ; return true ;
} }
@@ -653,17 +654,17 @@ static int doExtensionMcp4802 (char *progName, int pinBase, char *params)
int spi ; int spi ;
if ((params = extractInt (progName, params, &spi)) == NULL) if ((params = extractInt (progName, params, &spi)) == NULL)
return FALSE ; return false ;
if ((spi < 0) || (spi > 1)) if ((spi < 0) || (spi > 1))
{ {
verbError ("%s: SPI channel (%d) out of range", progName, spi) ; verbError ("%s: SPI channel (%d) out of range", progName, spi) ;
return FALSE ; return false ;
} }
mcp4802Setup (pinBase, spi) ; mcp4802Setup (pinBase, spi) ;
return TRUE ; return true ;
} }
@@ -677,7 +678,7 @@ static int doExtensionMcp4802 (char *progName, int pinBase, char *params)
static int doExtensionSn3218 (UNU char *progName, int pinBase, UNU char *params) static int doExtensionSn3218 (UNU char *progName, int pinBase, UNU char *params)
{ {
sn3218Setup (pinBase) ; sn3218Setup (pinBase) ;
return TRUE ; return true ;
} }
@@ -693,35 +694,35 @@ static int doExtensionMcp3422 (char *progName, int pinBase, char *params)
int i2c, sampleRate, gain ; int i2c, sampleRate, gain ;
if ((params = extractInt (progName, params, &i2c)) == NULL) if ((params = extractInt (progName, params, &i2c)) == NULL)
return FALSE ; return false ;
if ((i2c < 0x03) || (i2c > 0x77)) if ((i2c < 0x03) || (i2c > 0x77))
{ {
verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ; verbError ("%s: i2c address (0x%X) out of range", progName, i2c) ;
return FALSE ; return false ;
} }
if ((params = extractInt (progName, params, &sampleRate)) == NULL) if ((params = extractInt (progName, params, &sampleRate)) == NULL)
return FALSE ; return false ;
if ((sampleRate < 0) || (sampleRate > 3)) if ((sampleRate < 0) || (sampleRate > 3))
{ {
verbError ("%s: sample rate (%d) out of range", progName, sampleRate) ; verbError ("%s: sample rate (%d) out of range", progName, sampleRate) ;
return FALSE ; return false ;
} }
if ((params = extractInt (progName, params, &gain)) == NULL) if ((params = extractInt (progName, params, &gain)) == NULL)
return FALSE ; return false ;
if ((gain < 0) || (gain > 3)) if ((gain < 0) || (gain > 3))
{ {
verbError ("%s: gain (%d) out of range", progName, gain) ; verbError ("%s: gain (%d) out of range", progName, gain) ;
return FALSE ; return false ;
} }
mcp3422Setup (pinBase, i2c, sampleRate, gain) ; mcp3422Setup (pinBase, i2c, sampleRate, gain) ;
return TRUE ; return true ;
} }
@@ -738,35 +739,35 @@ static int doExtensionDrcS (char *progName, int pinBase, char *params)
int pins, baud ; int pins, baud ;
if ((params = extractInt (progName, params, &pins)) == NULL) if ((params = extractInt (progName, params, &pins)) == NULL)
return FALSE ; return false ;
if ((pins < 1) || (pins > 1000)) if ((pins < 1) || (pins > 1000))
{ {
verbError ("%s: pins (%d) out of range (2-1000)", progName, pins) ; verbError ("%s: pins (%d) out of range (2-1000)", progName, pins) ;
return FALSE ; return false ;
} }
if ((params = extractStr (progName, params, &port)) == NULL) if ((params = extractStr (progName, params, &port)) == NULL)
return FALSE ; return false ;
if (strlen (port) == 0) if (strlen (port) == 0)
{ {
verbError ("%s: serial port device name required", progName) ; verbError ("%s: serial port device name required", progName) ;
return FALSE ; return false ;
} }
if ((params = extractInt (progName, params, &baud)) == NULL) if ((params = extractInt (progName, params, &baud)) == NULL)
return FALSE ; return false ;
if ((baud < 1) || (baud > 4000000)) if ((baud < 1) || (baud > 4000000))
{ {
verbError ("%s: baud rate (%d) out of range", progName, baud) ; verbError ("%s: baud rate (%d) out of range", progName, baud) ;
return FALSE ; return false ;
} }
drcSetupSerial (pinBase, pins, port, baud) ; drcSetupSerial (pinBase, pins, port, baud) ;
return TRUE ; return true ;
} }
@@ -784,25 +785,25 @@ static int doExtensionDrcNet (char *progName, int pinBase, char *params)
char pPort [1024] ; char pPort [1024] ;
if ((params = extractInt (progName, params, &pins)) == NULL) if ((params = extractInt (progName, params, &pins)) == NULL)
return FALSE ; return false ;
if ((pins < 1) || (pins > 1000)) if ((pins < 1) || (pins > 1000))
{ {
verbError ("%s: pins (%d) out of range (2-1000)", progName, pins) ; verbError ("%s: pins (%d) out of range (2-1000)", progName, pins) ;
return FALSE ; return false ;
} }
if ((params = extractStr (progName, params, &ipAddress)) == NULL) if ((params = extractStr (progName, params, &ipAddress)) == NULL)
return FALSE ; return false ;
if (strlen (ipAddress) == 0) if (strlen (ipAddress) == 0)
{ {
verbError ("%s: ipAddress required", progName) ; verbError ("%s: ipAddress required", progName) ;
return FALSE ; return false ;
} }
if ((params = extractStr (progName, params, &port)) == NULL) if ((params = extractStr (progName, params, &port)) == NULL)
return FALSE ; return false ;
if (strlen (port) == 0) if (strlen (port) == 0)
{ {
@@ -811,12 +812,12 @@ static int doExtensionDrcNet (char *progName, int pinBase, char *params)
} }
if ((params = extractStr (progName, params, &password)) == NULL) if ((params = extractStr (progName, params, &password)) == NULL)
return FALSE ; return false ;
if (strlen (password) == 0) if (strlen (password) == 0)
{ {
verbError ("%s: password required", progName) ; verbError ("%s: password required", progName) ;
return FALSE ; return false ;
} }
return drcSetupNet (pinBase, pins, ipAddress, port, password) ; return drcSetupNet (pinBase, pins, ipAddress, port, password) ;
@@ -883,7 +884,7 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors)
if (!*p) // ran out of characters if (!*p) // ran out of characters
{ {
verbError ("%s: extension name not terminated by a colon", progName) ; verbError ("%s: extension name not terminated by a colon", progName) ;
return FALSE ; return false ;
} }
++p ; ++p ;
} }
@@ -894,7 +895,7 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors)
if (!isdigit (*p)) if (!isdigit (*p))
{ {
verbError ("%s: decimal pinBase number expected after extension name", progName) ; verbError ("%s: decimal pinBase number expected after extension name", progName) ;
return FALSE ; return false ;
} }
while (isdigit (*p)) while (isdigit (*p))
@@ -902,7 +903,7 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors)
if (pinBase > 2147483647) // 2^31-1 ... Lets be realistic here... if (pinBase > 2147483647) // 2^31-1 ... Lets be realistic here...
{ {
verbError ("%s: pinBase too large", progName) ; verbError ("%s: pinBase too large", progName) ;
return FALSE ; return false ;
} }
pinBase = pinBase * 10 + (*p - '0') ; pinBase = pinBase * 10 + (*p - '0') ;
@@ -912,7 +913,7 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors)
if (pinBase < 64) if (pinBase < 64)
{ {
verbError ("%s: pinBase (%d) too small. Minimum is 64.", progName, pinBase) ; verbError ("%s: pinBase (%d) too small. Minimum is 64.", progName, pinBase) ;
return FALSE ; return false ;
} }
// Search for extensions: // Search for extensions:
@@ -924,5 +925,5 @@ int loadWPiExtension (char *progName, char *extensionData, int printErrors)
} }
fprintf (stderr, "%s: extension %s not found", progName, extension) ; fprintf (stderr, "%s: extension %s not found", progName, extension) ;
return FALSE ; return false ;
} }

View File

@@ -26,6 +26,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <stdarg.h> #include <stdarg.h>
@@ -36,9 +37,6 @@
#include "network.h" #include "network.h"
#define TRUE (1==1)
#define FALSE (!TRUE)
// Local data // Local data
#define SALT_LEN 16 #define SALT_LEN 16

View File

@@ -26,6 +26,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <unistd.h> #include <unistd.h>
#include <string.h> #include <string.h>
#include <errno.h> #include <errno.h>
@@ -40,7 +41,7 @@
int noLocalPins = FALSE ; int noLocalPins = false ;
void runRemoteCommands (int fd) void runRemoteCommands (int fd)

View File

@@ -22,6 +22,7 @@
#include <arpa/inet.h> #include <arpa/inet.h>
#include <stdio.h> #include <stdio.h>
#include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h> #include <stdint.h>
#include <unistd.h> #include <unistd.h>
@@ -46,7 +47,7 @@
// Globals // Globals
static const char *usage = "[-h] [-d] [-g | -1 | -z] [[-x extension:pin:params] ...] password" ; static const char *usage = "[-h] [-d] [-g | -1 | -z] [[-x extension:pin:params] ...] password" ;
static int doDaemon = FALSE ; static int doDaemon = false ;
// //
@@ -156,7 +157,7 @@ int main (int argc, char *argv [])
exit (EXIT_FAILURE) ; exit (EXIT_FAILURE) ;
} }
doDaemon = TRUE ; doDaemon = true ;
daemonise (PIDFILE) ; daemonise (PIDFILE) ;
for (i = 2 ; i < argc ; ++i) for (i = 2 ; i < argc ; ++i)
@@ -216,7 +217,7 @@ int main (int argc, char *argv [])
for (i = 2 ; i < argc ; ++i) for (i = 2 ; i < argc ; ++i)
argv [i - 1] = argv [i] ; argv [i - 1] = argv [i] ;
--argc ; --argc ;
noLocalPins = TRUE ; noLocalPins = true ;
++wpiSetup ; ++wpiSetup ;
continue ; continue ;
} }
@@ -263,7 +264,7 @@ int main (int argc, char *argv [])
logMsg ("Loading extension: %s", argv [2]) ; logMsg ("Loading extension: %s", argv [2]) ;
if (!loadWPiExtension (argv [0], argv [2], TRUE)) if (!loadWPiExtension (argv [0], argv [2], true))
{ {
logMsg ("Extension load failed: %s", strerror (errno)) ; logMsg ("Extension load failed: %s", strerror (errno)) ;
exit (EXIT_FAILURE) ; exit (EXIT_FAILURE) ;