From 74a28addd6c476e7c8303f3c78c4c04d8d6944a1 Mon Sep 17 00:00:00 2001 From: Naoki Iwakami Date: Thu, 19 Jun 2025 14:49:25 +0000 Subject: [PATCH 01/14] Have wiringPiISR and wiringPiISR2 return error on failure in initialization The each function initializes the event listener loop in a spawned listener thread. The new thread does not report errors back to the original caller. So the function misses initialization errors. The code is fixed to initialize the event listener in the original thread before spawning the listener thread so that the function can pick up errors and return them to the user. --- wiringPi/wiringPi.c | 148 +++++++++++++++++++++++++++----------------- 1 file changed, 90 insertions(+), 58 deletions(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 50523dd..341d6df 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -2868,42 +2868,36 @@ int waitForInterruptClose(int pin) { } /* - * 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. + * interruptHandlerInit: + * Initializes an interrupt handler before starting the listener loop in a + * separate thread. + * 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) { - const char* strmode = ""; - int pin, EdgeMode, ret, fd, attr, i; - unsigned int readret; + const char* strmode = ""; + int EdgeMode, ret, attr; unsigned long debounce_period_us; - struct pollfd polls ; struct gpio_v2_line_config config; 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) { - return NULL; + if (wiringPiGpioDeviceGetFd() < 0) { + return -1; } - + EdgeMode = isrEdgeMode[pin]; debounce_period_us = isrDebouncePeriodUs[pin]; - + if (wiringPiDebug) { printf ("interruptHandlerV2: GPIO line %d, edge mode %d, debounce_period_us %lu \n", pin, EdgeMode, debounce_period_us) ; - } - + } + memset(&req, 0, sizeof(req)); memset(&config, 0, sizeof(config)); - + /* setup config */ config.flags = GPIO_V2_LINE_FLAG_INPUT; switch(EdgeMode) { @@ -2912,7 +2906,7 @@ void *interruptHandlerV2(void *arg) if (wiringPiDebug) { printf ("interruptHandlerV2: waitForInterruptMode edge mode INT_EDGE_SETUP - exiting\n") ; } - return NULL; + return 0; case INT_EDGE_FALLING: config.flags |= GPIO_V2_LINE_FLAG_EDGE_FALLING; strmode = "falling"; @@ -2927,7 +2921,7 @@ void *interruptHandlerV2(void *arg) break; } strcpy(req.consumer, "wiringpi_gpio_irq"); - + if (debounce_period_us) { attr = config.num_attrs; config.num_attrs++; @@ -2935,7 +2929,7 @@ void *interruptHandlerV2(void *arg) config.attrs[attr].attr.id = GPIO_V2_LINE_ATTR_ID_DEBOUNCE; config.attrs[attr].attr.debounce_period_us = debounce_period_us; } - + req.num_lines = 1; req.event_buffer_size = 45; req.offsets[0] = pin; @@ -2944,16 +2938,46 @@ void *interruptHandlerV2(void *arg) ret = ioctl(chipFd, GPIO_V2_GET_LINE_IOCTL, &req); if (ret == -1) { ReportDeviceError("interruptHandlerV2: get line event", pin , strmode, ret); - return NULL; + return -1; } - if (wiringPiDebug) - printf ("interruptHandlerV2: GPIO get line %d , mode %s succeded, fd=%d\n", pin, strmode, req.fd) ; + if (wiringPiDebug) { + 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 */ - fd = req.fd; isrFds [pin] = fd; - + (void)piHiPri (55) ; // Only effective if we run as root for (;;) { // check if event data is available, check if interruptHandlerV2 thread must be canceled @@ -2962,24 +2986,24 @@ void *interruptHandlerV2(void *arg) polls.fd = fd; polls.events = POLLIN | POLLPRI; polls.revents = 0; - + // 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 - + 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); - pthread_exit(NULL); + pthread_exit(NULL); return NULL; // never landing here - } else if (ret == 0) { -// if (wiringPiDebug) + } else if (ret == 0) { +// if (wiringPiDebug) // printf("interruptHandlerV2: timeout: poll returned=%d\n", ret); continue; } else { if (wiringPiDebug) 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 */ readret = read(fd, &evdat, sizeof(evdat)); if (readret >= sizeof(evdat[0])) { @@ -2989,7 +3013,7 @@ void *interruptHandlerV2(void *arg) ret = readret/sizeof(evdat[0]); // number of events read from fd for (i = 0; i < ret; ++i) { 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); wfiStatus.statusOK = 1; wfiStatus.pinBCM = pin; @@ -3006,10 +3030,10 @@ void *interruptHandlerV2(void *arg) break; default: wfiStatus.edge = INT_EDGE_SETUP; // edge = 0 - if (wiringPiDebug) + if (wiringPiDebug) printf("waitForInterrupt2: unknown event\n"); break; - } + } wfiStatus.timeStamp_us = evdat[i].timestamp_ns/1000LL; if (wiringPiDebug) { printf( "interruptHandlerV2: call isr function\n"); @@ -3033,7 +3057,7 @@ void *interruptHandlerV2(void *arg) else { // if thread canceled we do not reach this point, read(...) does not return, is Cancellation Point if (wiringPiDebug) printf ("interruptHandlerV2: reading events from fd received signal, exit thread\n"); - pthread_exit(NULL); + pthread_exit(NULL); return NULL; // never landing here } } @@ -3041,9 +3065,8 @@ void *interruptHandlerV2(void *arg) } } - /* - * wiringPiISR: + * wiringPiISRInternal: * Pi Specific. * Take the details and create an interrupt handler that will do a call- * back to the user supplied function. @@ -3072,30 +3095,39 @@ int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiSta isrFunctions[pin] = functionClassic; isrEdgeMode[pin] = edgeMode; isrDebouncePeriodUs[pin] = debounce_period_us; - + if (wiringPiDebug) { printf("wiringPi: mutex in\n"); } pthread_mutex_lock (&pinMutex) ; - pinPass = pin ; - if (wiringPiDebug) { - printf("wiringPi: pthread_create before 0x%lX\n", (unsigned long)isrThreads[pin]); + struct interrupt_handler_params params = { + .pin = pin, + }; + params.fd = interruptHandlerInit(pin); + if (params.fd < 0) { + pthread_mutex_unlock (&pinMutex) ; + return -1; } - if (pthread_create (&isrThreads[pin], NULL, interruptHandlerV2, &pin)==0) { + + pinPass = pin ; + if (params.fd > 0) { 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) - delay (1) ; */ - // wait so that interruptHandler is up und running. - // when interruptHandler is running, the calling function wiringPiISR - // must be still alive, otherwise the thread argument &pin points into nirwana, - // when it is picked up from interruptHandler. - delay (10); - } else { - if (wiringPiDebug) { - printf("wiringPi: pthread_create failed\n"); + if (pthread_create (&isrThreads[pin], NULL, interruptHandlerV2, ¶ms)==0) { + if (wiringPiDebug) { + printf("wiringPi: pthread_create successed, 0x%lX\n", (unsigned long)isrThreads[pin]); + } + } 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 ¶m points into nirwana, + // when it is picked up from interruptHandlerV2. + delay(10); } if (wiringPiDebug) { From e020bb8b6c0f0222bf6a758f4ac333829e5b0ab1 Mon Sep 17 00:00:00 2001 From: Naoki Iwakami Date: Thu, 19 Jun 2025 19:37:03 +0000 Subject: [PATCH 02/14] Fix issues found by tests --- wiringPi/wiringPi.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 341d6df..aa165ce 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -2876,11 +2876,10 @@ int waitForInterruptClose(int pin) { ********************************************************************************* */ -static int interruptHandlerInit(int pin) +static int interruptHandlerInit(int pin, int EdgeMode, unsigned long debounce_period_us) { const char* strmode = ""; - int EdgeMode, ret, attr; - unsigned long debounce_period_us; + int ret, attr; struct gpio_v2_line_config config; struct gpio_v2_line_request req; @@ -2888,9 +2887,6 @@ static int interruptHandlerInit(int pin) return -1; } - EdgeMode = isrEdgeMode[pin]; - debounce_period_us = isrDebouncePeriodUs[pin]; - if (wiringPiDebug) { printf ("interruptHandlerV2: GPIO line %d, edge mode %d, debounce_period_us %lu \n", pin, EdgeMode, debounce_period_us) ; } @@ -3087,15 +3083,9 @@ int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiSta printf("wiringPi: wiringPiISR pin %d, edgeMode %d\n", pin, edgeMode); } 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) { printf("wiringPi: mutex in\n"); } @@ -3103,12 +3093,19 @@ int wiringPiISRInternal(int pin, int edgeMode, void (*function)(struct WPIWfiSta struct interrupt_handler_params params = { .pin = pin, }; - params.fd = interruptHandlerInit(pin); + params.fd = interruptHandlerInit(pin, edgeMode, debounce_period_us); if (params.fd < 0) { pthread_mutex_unlock (&pinMutex) ; return -1; } + // 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) { From e4ab8a78b3a5b9e472380d105bbbd813c3d56519 Mon Sep 17 00:00:00 2001 From: Naoki Iwakami Date: Fri, 29 Aug 2025 05:24:49 +0000 Subject: [PATCH 03/14] Add gtest cases for ISR --- wiringPi/gtest/.gitignore | 2 + wiringPi/gtest/Makefile | 92 ++++++++++++ wiringPi/gtest/README.md | 26 ++++ wiringPi/gtest/run_isr.cpp | 31 ++++ wiringPi/gtest/test_isr_both.cpp | 51 +++++++ .../test_isr_conflict_between_processes.cpp | 68 +++++++++ wiringPi/gtest/test_isr_falling.cpp | 57 ++++++++ wiringPi/gtest/test_isr_restart.cpp | 67 +++++++++ wiringPi/gtest/test_isr_restart2.cpp | 109 ++++++++++++++ wiringPi/gtest/test_isr_rising.cpp | 80 +++++++++++ wiringPi/gtest/test_isr_rising2.cpp | 135 ++++++++++++++++++ 11 files changed, 718 insertions(+) create mode 100644 wiringPi/gtest/.gitignore create mode 100644 wiringPi/gtest/Makefile create mode 100644 wiringPi/gtest/README.md create mode 100644 wiringPi/gtest/run_isr.cpp create mode 100644 wiringPi/gtest/test_isr_both.cpp create mode 100644 wiringPi/gtest/test_isr_conflict_between_processes.cpp create mode 100644 wiringPi/gtest/test_isr_falling.cpp create mode 100644 wiringPi/gtest/test_isr_restart.cpp create mode 100644 wiringPi/gtest/test_isr_restart2.cpp create mode 100644 wiringPi/gtest/test_isr_rising.cpp create mode 100644 wiringPi/gtest/test_isr_rising2.cpp diff --git a/wiringPi/gtest/.gitignore b/wiringPi/gtest/.gitignore new file mode 100644 index 0000000..b868581 --- /dev/null +++ b/wiringPi/gtest/.gitignore @@ -0,0 +1,2 @@ +bin +googletest-main diff --git a/wiringPi/gtest/Makefile b/wiringPi/gtest/Makefile new file mode 100644 index 0000000..87e679c --- /dev/null +++ b/wiringPi/gtest/Makefile @@ -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 BCM1 <-> BCM12 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 \ No newline at end of file diff --git a/wiringPi/gtest/README.md b/wiringPi/gtest/README.md new file mode 100644 index 0000000..e4c277d --- /dev/null +++ b/wiringPi/gtest/README.md @@ -0,0 +1,26 @@ +## Quick Start + +g++ is required to build the test cases. + +Connect wPi pin 31 (BCM 1) and wPi pin 26 (BCM 12) to run ISR tests. +Also, wPi pin 28 (BCM 20) 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. diff --git a/wiringPi/gtest/run_isr.cpp b/wiringPi/gtest/run_isr.cpp new file mode 100644 index 0000000..8f4a61b --- /dev/null +++ b/wiringPi/gtest/run_isr.cpp @@ -0,0 +1,31 @@ +/* + * Helper program of test_conflict_between_processes. + * + * The program configures ISR on pin 31 (BCM 1) and polls for a termination request. + */ +#include +#include +#include + +#define LISTENER_PIN 31 // BCM 1 + +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"); +} \ No newline at end of file diff --git a/wiringPi/gtest/test_isr_both.cpp b/wiringPi/gtest/test_isr_both.cpp new file mode 100644 index 0000000..09fb58d --- /dev/null +++ b/wiringPi/gtest/test_isr_both.cpp @@ -0,0 +1,51 @@ +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 + +/** + * 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); +} \ No newline at end of file diff --git a/wiringPi/gtest/test_isr_conflict_between_processes.cpp b/wiringPi/gtest/test_isr_conflict_between_processes.cpp new file mode 100644 index 0000000..31f954b --- /dev/null +++ b/wiringPi/gtest/test_isr_conflict_between_processes.cpp @@ -0,0 +1,68 @@ +#include +#include +#include +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 +#define ANOTHER_LISTENER_PIN 28 // BCM 20 + +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); +} diff --git a/wiringPi/gtest/test_isr_falling.cpp b/wiringPi/gtest/test_isr_falling.cpp new file mode 100644 index 0000000..bfda8c0 --- /dev/null +++ b/wiringPi/gtest/test_isr_falling.cpp @@ -0,0 +1,57 @@ +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 + +/** + * 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); +} \ No newline at end of file diff --git a/wiringPi/gtest/test_isr_restart.cpp b/wiringPi/gtest/test_isr_restart.cpp new file mode 100644 index 0000000..c7a5c7a --- /dev/null +++ b/wiringPi/gtest/test_isr_restart.cpp @@ -0,0 +1,67 @@ +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 +#define ANOTHER_LISTENER_PIN 28 // BCM 20 + +/** + * 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); + delay(100); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + EXPECT_EQ(count, 1u); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 0u); +} diff --git a/wiringPi/gtest/test_isr_restart2.cpp b/wiringPi/gtest/test_isr_restart2.cpp new file mode 100644 index 0000000..173d3d5 --- /dev/null +++ b/wiringPi/gtest/test_isr_restart2.cpp @@ -0,0 +1,109 @@ +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 +#define ANOTHER_LISTENER_PIN 28 // BCM 20 + +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(10); + EXPECT_EQ(count, 1); + EXPECT_EQ(count2, 1); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 1); + EXPECT_EQ(count2, 1); + + // stop the ISR + EXPECT_EQ(wiringPiISRStop(LISTENER_PIN), 0); + delay(100); + digitalWrite(TRIGGER_PIN, HIGH); + delay(10); + 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(10); + EXPECT_EQ(count, 1); + EXPECT_EQ(count2, 1); + EXPECT_EQ(count3, 0); + + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 2); + EXPECT_EQ(count2, 1); + EXPECT_EQ(count3, -1); +} diff --git a/wiringPi/gtest/test_isr_rising.cpp b/wiringPi/gtest/test_isr_rising.cpp new file mode 100644 index 0000000..9a41b14 --- /dev/null +++ b/wiringPi/gtest/test_isr_rising.cpp @@ -0,0 +1,80 @@ +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 +#define ANOTHER_LISTENER_PIN 28 // BCM 20 + +/** + * 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); +} diff --git a/wiringPi/gtest/test_isr_rising2.cpp b/wiringPi/gtest/test_isr_rising2.cpp new file mode 100644 index 0000000..b40ea4c --- /dev/null +++ b/wiringPi/gtest/test_isr_rising2.cpp @@ -0,0 +1,135 @@ +#include +#include +#include + +#define TRIGGER_PIN 26 // BCM 12 +#define LISTENER_PIN 31 // BCM 1 +#define ANOTHER_LISTENER_PIN 28 // BCM 20 + +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(10); + EXPECT_EQ(count, 1u); + EXPECT_EQ(count2, 1u); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + 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) { + delay(10); + digitalWrite(TRIGGER_PIN, i % 2); + } + delay(10); + EXPECT_EQ(count, 3u); +} + +TEST_F(ISRRising2, Debounce) { + delay(10); + for (int i = 0; i < 7; ++i) { + digitalWrite(TRIGGER_PIN, (i + 1) % 2); + } + delay(10); + 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(10); + EXPECT_EQ(count, 1u); + EXPECT_EQ(count2, 1u); + digitalWrite(TRIGGER_PIN, LOW); + delay(10); + EXPECT_EQ(count, 1u); + EXPECT_EQ(count2, 1u); + + delay(10); + count = 0; + for (int i = 0; i < 7; ++i) { + digitalWrite(TRIGGER_PIN, (i + 1) % 2); + } + delay(10); + EXPECT_EQ(count, 1u); +} From b54a60a59838107c0cecf730bf3e6cedae85e456 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 13 Sep 2025 15:48:34 +0200 Subject: [PATCH 04/14] #396 change pins to default unit test hardware (Pi1 comp.) --- wiringPi/gtest/Makefile | 2 +- wiringPi/gtest/README.md | 4 ++-- wiringPi/gtest/run_isr.cpp | 4 ++-- wiringPi/gtest/test_isr_both.cpp | 4 ++-- wiringPi/gtest/test_isr_conflict_between_processes.cpp | 6 +++--- wiringPi/gtest/test_isr_falling.cpp | 4 ++-- wiringPi/gtest/test_isr_restart.cpp | 6 +++--- wiringPi/gtest/test_isr_restart2.cpp | 6 +++--- wiringPi/gtest/test_isr_rising.cpp | 6 +++--- wiringPi/gtest/test_isr_rising2.cpp | 6 +++--- 10 files changed, 24 insertions(+), 24 deletions(-) diff --git a/wiringPi/gtest/Makefile b/wiringPi/gtest/Makefile index 87e679c..16ce2f8 100644 --- a/wiringPi/gtest/Makefile +++ b/wiringPi/gtest/Makefile @@ -16,7 +16,7 @@ BIN_DIR := bin RUN_ISR_SRC := run_isr.cpp RUN_ISR_BIN := $(BIN_DIR)/run_isr -# Need BCM1 <-> BCM12 connection +# Need BCM17 <-> BCM18 connection TEST_SRCS := \ test_isr_both.cpp \ test_isr_conflict_between_processes.cpp \ diff --git a/wiringPi/gtest/README.md b/wiringPi/gtest/README.md index e4c277d..b061c05 100644 --- a/wiringPi/gtest/README.md +++ b/wiringPi/gtest/README.md @@ -2,8 +2,8 @@ g++ is required to build the test cases. -Connect wPi pin 31 (BCM 1) and wPi pin 26 (BCM 12) to run ISR tests. -Also, wPi pin 28 (BCM 20) should be unconnected. +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: diff --git a/wiringPi/gtest/run_isr.cpp b/wiringPi/gtest/run_isr.cpp index 8f4a61b..9937946 100644 --- a/wiringPi/gtest/run_isr.cpp +++ b/wiringPi/gtest/run_isr.cpp @@ -1,13 +1,13 @@ /* * Helper program of test_conflict_between_processes. * - * The program configures ISR on pin 31 (BCM 1) and polls for a termination request. + * The program configures ISR on pin 1 (BCM 18) and polls for a termination request. */ #include #include #include -#define LISTENER_PIN 31 // BCM 1 +#define LISTENER_PIN 1 // BCM 18 static uint8_t ok_to_stop = 0; static void noop() { diff --git a/wiringPi/gtest/test_isr_both.cpp b/wiringPi/gtest/test_isr_both.cpp index 09fb58d..a404e73 100644 --- a/wiringPi/gtest/test_isr_both.cpp +++ b/wiringPi/gtest/test_isr_both.cpp @@ -2,8 +2,8 @@ #include #include -#define TRIGGER_PIN 26 // BCM 12 -#define LISTENER_PIN 31 // BCM 1 +#define TRIGGER_PIN 0 // BCM 17 +#define LISTENER_PIN 1 // BCM 18 /** * Tests ISR for both edges. diff --git a/wiringPi/gtest/test_isr_conflict_between_processes.cpp b/wiringPi/gtest/test_isr_conflict_between_processes.cpp index 31f954b..2ac955c 100644 --- a/wiringPi/gtest/test_isr_conflict_between_processes.cpp +++ b/wiringPi/gtest/test_isr_conflict_between_processes.cpp @@ -5,9 +5,9 @@ #include #include -#define TRIGGER_PIN 26 // BCM 12 -#define LISTENER_PIN 31 // BCM 1 -#define ANOTHER_LISTENER_PIN 28 // BCM 20 +#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"); diff --git a/wiringPi/gtest/test_isr_falling.cpp b/wiringPi/gtest/test_isr_falling.cpp index bfda8c0..ee52e6a 100644 --- a/wiringPi/gtest/test_isr_falling.cpp +++ b/wiringPi/gtest/test_isr_falling.cpp @@ -2,8 +2,8 @@ #include #include -#define TRIGGER_PIN 26 // BCM 12 -#define LISTENER_PIN 31 // BCM 1 +#define TRIGGER_PIN 0 // BCM 17 +#define LISTENER_PIN 1 // BCM 18 /** * Tests ISR for falling edges. diff --git a/wiringPi/gtest/test_isr_restart.cpp b/wiringPi/gtest/test_isr_restart.cpp index c7a5c7a..0930bab 100644 --- a/wiringPi/gtest/test_isr_restart.cpp +++ b/wiringPi/gtest/test_isr_restart.cpp @@ -2,9 +2,9 @@ #include #include -#define TRIGGER_PIN 26 // BCM 12 -#define LISTENER_PIN 31 // BCM 1 -#define ANOTHER_LISTENER_PIN 28 // BCM 20 +#define TRIGGER_PIN 0 // BCM 17 +#define LISTENER_PIN 1 // BCM 18 +#define ANOTHER_LISTENER_PIN 6 // BCM 25 /** * Tests restarting ISR. diff --git a/wiringPi/gtest/test_isr_restart2.cpp b/wiringPi/gtest/test_isr_restart2.cpp index 173d3d5..c7225c0 100644 --- a/wiringPi/gtest/test_isr_restart2.cpp +++ b/wiringPi/gtest/test_isr_restart2.cpp @@ -2,9 +2,9 @@ #include #include -#define TRIGGER_PIN 26 // BCM 12 -#define LISTENER_PIN 31 // BCM 1 -#define ANOTHER_LISTENER_PIN 28 // BCM 20 +#define TRIGGER_PIN 0 // BCM 17 +#define LISTENER_PIN 1 // BCM 18 +#define ANOTHER_LISTENER_PIN 6 // BCM 25 struct counters { int32_t *primary; diff --git a/wiringPi/gtest/test_isr_rising.cpp b/wiringPi/gtest/test_isr_rising.cpp index 9a41b14..1ad7369 100644 --- a/wiringPi/gtest/test_isr_rising.cpp +++ b/wiringPi/gtest/test_isr_rising.cpp @@ -2,9 +2,9 @@ #include #include -#define TRIGGER_PIN 26 // BCM 12 -#define LISTENER_PIN 31 // BCM 1 -#define ANOTHER_LISTENER_PIN 28 // BCM 20 +#define TRIGGER_PIN 0 // BCM 17 +#define LISTENER_PIN 1 // BCM 18 +#define ANOTHER_LISTENER_PIN 6 // BCM 25 /** * Tests ISR for rising edges. diff --git a/wiringPi/gtest/test_isr_rising2.cpp b/wiringPi/gtest/test_isr_rising2.cpp index b40ea4c..4e1e6fe 100644 --- a/wiringPi/gtest/test_isr_rising2.cpp +++ b/wiringPi/gtest/test_isr_rising2.cpp @@ -2,9 +2,9 @@ #include #include -#define TRIGGER_PIN 26 // BCM 12 -#define LISTENER_PIN 31 // BCM 1 -#define ANOTHER_LISTENER_PIN 28 // BCM 20 +#define TRIGGER_PIN 0 // BCM 17 +#define LISTENER_PIN 1 // BCM 18 +#define ANOTHER_LISTENER_PIN 6 // BCM 25 struct counters { uint32_t *primary; From a687840a872e0fe89da12fef6245777a63c907fd Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Fri, 19 Sep 2025 20:11:27 +0200 Subject: [PATCH 05/14] #396 longer delay for Pi1 comp. --- wiringPi/gtest/test_isr_restart2.cpp | 10 +++++----- wiringPi/gtest/test_isr_rising2.cpp | 21 +++++++++++---------- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/wiringPi/gtest/test_isr_restart2.cpp b/wiringPi/gtest/test_isr_restart2.cpp index c7225c0..be0d14b 100644 --- a/wiringPi/gtest/test_isr_restart2.cpp +++ b/wiringPi/gtest/test_isr_restart2.cpp @@ -72,11 +72,11 @@ TEST_F(ISRRestart2, RestartISR2) { EXPECT_EQ(count, 0); EXPECT_EQ(count2, 0); digitalWrite(TRIGGER_PIN, HIGH); - delay(10); + delay(20); EXPECT_EQ(count, 1); EXPECT_EQ(count2, 1); digitalWrite(TRIGGER_PIN, LOW); - delay(10); + delay(20); EXPECT_EQ(count, 1); EXPECT_EQ(count2, 1); @@ -84,7 +84,7 @@ TEST_F(ISRRestart2, RestartISR2) { EXPECT_EQ(wiringPiISRStop(LISTENER_PIN), 0); delay(100); digitalWrite(TRIGGER_PIN, HIGH); - delay(10); + delay(20); EXPECT_EQ(count, 1); EXPECT_EQ(count2, 1); EXPECT_EQ(count3, 0); @@ -96,13 +96,13 @@ TEST_F(ISRRestart2, RestartISR2) { 0); delay(100); digitalWrite(TRIGGER_PIN, HIGH); - delay(10); + delay(20); EXPECT_EQ(count, 1); EXPECT_EQ(count2, 1); EXPECT_EQ(count3, 0); digitalWrite(TRIGGER_PIN, LOW); - delay(10); + delay(20); EXPECT_EQ(count, 2); EXPECT_EQ(count2, 1); EXPECT_EQ(count3, -1); diff --git a/wiringPi/gtest/test_isr_rising2.cpp b/wiringPi/gtest/test_isr_rising2.cpp index 4e1e6fe..d23b5dd 100644 --- a/wiringPi/gtest/test_isr_rising2.cpp +++ b/wiringPi/gtest/test_isr_rising2.cpp @@ -72,11 +72,11 @@ TEST_F(ISRRising2, Fundamental) { EXPECT_EQ(count, 0u); EXPECT_EQ(count2, 0u); digitalWrite(TRIGGER_PIN, HIGH); - delay(10); + delay(20); EXPECT_EQ(count, 1u); EXPECT_EQ(count2, 1u); digitalWrite(TRIGGER_PIN, LOW); - delay(10); + delay(20); EXPECT_EQ(count, 1u); EXPECT_EQ(count2, 1u); } @@ -86,19 +86,19 @@ TEST_F(ISRRising2, ThreeTriggers) { delay(10); count = 0; for (int i = 0; i < 6; ++i) { - delay(10); + delay(20); digitalWrite(TRIGGER_PIN, i % 2); } - delay(10); + delay(20); EXPECT_EQ(count, 3u); } TEST_F(ISRRising2, Debounce) { - delay(10); + delay(20); for (int i = 0; i < 7; ++i) { digitalWrite(TRIGGER_PIN, (i + 1) % 2); } - delay(10); + delay(20); EXPECT_EQ(count, 1u); } @@ -117,19 +117,20 @@ TEST_F(ISRRising2, ISRInitConflict) { EXPECT_EQ(count, 0u); EXPECT_EQ(count2, 0u); digitalWrite(TRIGGER_PIN, HIGH); - delay(10); + delay(20); EXPECT_EQ(count, 1u); EXPECT_EQ(count2, 1u); digitalWrite(TRIGGER_PIN, LOW); - delay(10); + delay(20); EXPECT_EQ(count, 1u); EXPECT_EQ(count2, 1u); - delay(10); + delay(20); count = 0; for (int i = 0; i < 7; ++i) { + delay(1); digitalWrite(TRIGGER_PIN, (i + 1) % 2); } - delay(10); + delay(20); EXPECT_EQ(count, 1u); } From b3394383eb732f2b5e204f176254b428df2cc18f Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 28 Sep 2025 19:19:26 +0200 Subject: [PATCH 06/14] #396 fix unit test problems --- wiringPi/gtest/test_isr_restart.cpp | 1 + wiringPi/gtest/test_isr_rising.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/wiringPi/gtest/test_isr_restart.cpp b/wiringPi/gtest/test_isr_restart.cpp index 0930bab..29c2f79 100644 --- a/wiringPi/gtest/test_isr_restart.cpp +++ b/wiringPi/gtest/test_isr_restart.cpp @@ -57,6 +57,7 @@ TEST_F(ISRRestart, RestartISR) { EXPECT_EQ( wiringPiISR(LISTENER_PIN, INT_EDGE_FALLING, ISRRestart::TriggerCountDown), 0); + count=1; delay(100); digitalWrite(TRIGGER_PIN, HIGH); delay(10); diff --git a/wiringPi/gtest/test_isr_rising.cpp b/wiringPi/gtest/test_isr_rising.cpp index 1ad7369..ea5473c 100644 --- a/wiringPi/gtest/test_isr_rising.cpp +++ b/wiringPi/gtest/test_isr_rising.cpp @@ -4,7 +4,7 @@ #define TRIGGER_PIN 0 // BCM 17 #define LISTENER_PIN 1 // BCM 18 -#define ANOTHER_LISTENER_PIN 6 // BCM 25 +#define ANOTHER_LISTENER_PIN 26 // BCM 12 /** * Tests ISR for rising edges. From 4ef1f91cbb44f0d9266aee29e058bc453438d6e5 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 28 Sep 2025 19:43:52 +0200 Subject: [PATCH 07/14] #396 fix unit test problems --- wiringPi/gtest/test_isr_restart2.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wiringPi/gtest/test_isr_restart2.cpp b/wiringPi/gtest/test_isr_restart2.cpp index be0d14b..df2ca5e 100644 --- a/wiringPi/gtest/test_isr_restart2.cpp +++ b/wiringPi/gtest/test_isr_restart2.cpp @@ -4,7 +4,7 @@ #define TRIGGER_PIN 0 // BCM 17 #define LISTENER_PIN 1 // BCM 18 -#define ANOTHER_LISTENER_PIN 6 // BCM 25 +#define ANOTHER_LISTENER_PIN 26 // BCM 12 struct counters { int32_t *primary; From c9f08c9e7b937f2cde8a9eeabb573071ec42b4ca Mon Sep 17 00:00:00 2001 From: mstroh Date: Sun, 2 Nov 2025 18:36:57 +0100 Subject: [PATCH 08/14] #407 de fix ISR example --- documentation/deutsch/functions.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 0c86b55..8b78d56 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -473,7 +473,7 @@ static void wfi(struct WPIWfiStatus wfiStatus, void* userdata) { edgeType = "falling"; else 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) { digitalWrite (OUTpin, HIGH); toggle = 1; @@ -500,19 +500,19 @@ int main (void) 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); - if (wfiStatus.status < 0) { + if (wfiStatus.statusOK < 0) { printf("waitForInterrupt returned error\n"); pinMode(OUTpin, INPUT); return 0; } - else if (wfiStatus.status == 0) { + else if (wfiStatus.statusOK == 0) { printf("waitForInterrupt timed out\n\n"); } else { 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 - 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); From 08cf61daff6e3947c9f34655b5e25ce3ba601574 Mon Sep 17 00:00:00 2001 From: mstroh Date: Sun, 2 Nov 2025 18:39:14 +0100 Subject: [PATCH 09/14] #407 en fix ISR example --- documentation/english/functions.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/documentation/english/functions.md b/documentation/english/functions.md index f13874a..739f9ab 100644 --- a/documentation/english/functions.md +++ b/documentation/english/functions.md @@ -497,19 +497,19 @@ int main (void) 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); - if (wfiStatus.status < 0) { + if (wfiStatus.statusOK < 0) { printf("waitForInterrupt returned error\n"); pinMode(OUTpin, INPUT); return 0; } - else if (wfiStatus.status == 0) { + else if (wfiStatus.statusOK == 0) { printf("waitForInterrupt timed out\n\n"); } else { 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 - 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); From 0f76f5e116a01f1c775b07308133c6f68b9f29f7 Mon Sep 17 00:00:00 2001 From: mstroh Date: Sun, 2 Nov 2025 18:45:03 +0100 Subject: [PATCH 10/14] #407 en fix ISR example --- documentation/english/functions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/english/functions.md b/documentation/english/functions.md index 739f9ab..6875205 100644 --- a/documentation/english/functions.md +++ b/documentation/english/functions.md @@ -470,7 +470,7 @@ static void wfi(struct WPIWfiStatus wfiStatus, void* userdata) { edgeType = "falling"; else 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) { digitalWrite (OUTpin, HIGH); toggle = 1; From 22a96cb61f23ededcd273bfaae5162fd9d16ecfd Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sun, 2 Nov 2025 21:23:46 +0100 Subject: [PATCH 11/14] #408 gpio -x unit test --- gpio/test/gpio_test1_piface1.sh | 90 +++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100755 gpio/test/gpio_test1_piface1.sh diff --git a/gpio/test/gpio_test1_piface1.sh b/gpio/test/gpio_test1_piface1.sh new file mode 100755 index 0000000..5840830 --- /dev/null +++ b/gpio/test/gpio_test1_piface1.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +echo -e "πŸ”§ Starting relay unit test for MCP23S17@Piface unit test hw\n\n" + +# set pin 200–207 as output +for i in {200..207}; do + gpio -x mcp23s17:200:0:0 mode $i out +done + +# set pin 208–215 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." + From 2d22070aa37b66e11f37baf6d15ad59ffc5a4e3e Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 10 Jan 2026 17:06:26 +0100 Subject: [PATCH 12/14] #411 support CS0-4 --- documentation/deutsch/functions.md | 4 ++-- documentation/english/functions.md | 4 ++-- wiringPi/wiringPiSPI.c | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/documentation/deutsch/functions.md b/documentation/deutsch/functions.md index 8b78d56..f0c87b3 100644 --- a/documentation/deutsch/functions.md +++ b/documentation/deutsch/functions.md @@ -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) ``` -``number``: SPI Nummer (typisch 0, bei Compute Modul 0-7). -``channel``: SPI Kanal (typisch 0 oder 1, bei Compute Modul 0-3). +``number``: SPI Nummer (typisch 0, bei Compute Modul 0-6). +``channel``: SPI Kanal (typisch 0 oder 1, bei Compute Modul oder entsprechenden overlay 0-4). ``speed``: SPI Taktrate. ``mode``: SPI Modus (https://www.kernel.org/doc/Documentation/spi/spidev). ``RΓΌckgabewert``: Datei Handle zum SPI-Bus diff --git a/documentation/english/functions.md b/documentation/english/functions.md index 6875205..f1ec746 100644 --- a/documentation/english/functions.md +++ b/documentation/english/functions.md @@ -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); ``` -``number``: SPI number (typically 0, on Compute Module 0-7). -``channel``: SPI channel (typically 0 or 1, on Compute Module 0-3). +``number``: SPI number (typically 0, on Compute Module 0-6). +``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). ``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. diff --git a/wiringPi/wiringPiSPI.c b/wiringPi/wiringPiSPI.c index 581a079..e182523 100644 --- a/wiringPi/wiringPiSPI.c +++ b/wiringPi/wiringPiSPI.c @@ -44,9 +44,11 @@ //static const char *spiDev1 = "/dev/spidev0.1" ; static const uint8_t spiBPW = 8 ; 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_MaxSPIChannels = 3 ; +const uint8_t WPI_MaxSPIChannels = 5 ; static uint32_t spiSpeeds [7][3] = From c8c6790926b6e6c5c51b485ab703c27771c8cdb6 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 10 Jan 2026 17:15:10 +0100 Subject: [PATCH 13/14] adjust Pi4 speed, Kernel 6.12.47, Bookwork, 2026 --- wiringPi/test/wiringpi_test7_bench.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/wiringPi/test/wiringpi_test7_bench.c b/wiringPi/test/wiringpi_test7_bench.c index 9c0f221..ffdf367 100644 --- a/wiringPi/test/wiringpi_test7_bench.c +++ b/wiringPi/test/wiringpi_test7_bench.c @@ -83,7 +83,8 @@ int main (void) { case PI_MODEL_400: case PI_MODEL_CM4: 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 fExpectTimepinMode = 0.121; //us fWriteReadDelayFactor = 1.86; From cd882f6cf3271ed29a578d7b0471161e7ef8e169 Mon Sep 17 00:00:00 2001 From: mstroh76 Date: Sat, 10 Jan 2026 17:35:57 +0100 Subject: [PATCH 14/14] #412 Update Version und date to 2026 --- VERSION | 2 +- gpio/gpio.1 | 2 +- gpio/gpio.c | 6 +++--- gpio/readall.c | 2 +- version.h | 4 ++-- wiringPi/wiringPi.c | 2 +- wiringPi/wiringPi.h | 2 +- wiringPi/wiringPiI2C.c | 2 +- wiringPi/wiringPiI2C.h | 2 +- wiringPi/wiringPiSPI.c | 2 +- wiringPi/wiringPiSPI.h | 2 +- 11 files changed, 14 insertions(+), 14 deletions(-) diff --git a/VERSION b/VERSION index 5174c53..b2fb78a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.16 +3.18 diff --git a/gpio/gpio.1 b/gpio/gpio.1 index 4d76671..e99b66a 100644 --- a/gpio/gpio.1 +++ b/gpio/gpio.1 @@ -282,7 +282,7 @@ Please report bugs to https://github.com/WiringPi/WiringPi/issues .SH COPYRIGHT -Copyright (c) 2012-2025 Gordon Henderson and contributors +Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors .br This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. diff --git a/gpio/gpio.c b/gpio/gpio.c index 8eae4d1..bf7d23d 100644 --- a/gpio/gpio.c +++ b/gpio/gpio.c @@ -2,7 +2,7 @@ * gpio.c: * Swiss-Army-Knife, Set-UID command-line interface to the Raspberry * Pi's GPIO. - * Copyright (c) 2012-2025 Gordon Henderson and contributors + * Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors *********************************************************************** * This file is part of wiringPi: * https://github.com/WiringPi/WiringPi/ @@ -916,7 +916,7 @@ static void doVersion (char *argv []) wiringPiVersion (&vMaj, &vMin) ; printf ("gpio version: %d.%d\n", vMaj, vMin) ; - printf ("Copyright (c) 2012-2025 Gordon Henderson and contributors\n") ; + printf ("Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors\n") ; printf ("This is free software with ABSOLUTELY NO WARRANTY.\n") ; printf ("For details type: %s -warranty\n", argv [0]) ; printf ("\n") ; @@ -1033,7 +1033,7 @@ int main (int argc, char *argv []) if (strcasecmp (argv [1], "-warranty") == 0) { printf ("gpio version: %s\n", VERSION) ; - printf ("Copyright (c) 2012-2025 Gordon Henderson and contributors\n") ; + printf ("Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors\n") ; printf ("\n") ; printf (" This program is free software; you can redistribute it and/or modify\n") ; printf (" it under the terms of the GNU Leser General Public License as published\n") ; diff --git a/gpio/readall.c b/gpio/readall.c index 3812e53..d75c414 100644 --- a/gpio/readall.c +++ b/gpio/readall.c @@ -1,7 +1,7 @@ /* * readall.c: * The readall functions - getting a bit big, so split them out. - * Copyright (c) 2012-2024 Gordon Henderson and contributors + * Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors *********************************************************************** * This file is part of wiringPi: * https://github.com/WiringPi/WiringPi/ diff --git a/version.h b/version.h index 5ea1e8c..5d9ebc5 100644 --- a/version.h +++ b/version.h @@ -1,3 +1,3 @@ -#define VERSION "3.16" +#define VERSION "3.18" #define VERSION_MAJOR 3 -#define VERSION_MINOR 16 +#define VERSION_MINOR 18 diff --git a/wiringPi/wiringPi.c b/wiringPi/wiringPi.c index 0cc75a5..d387d1a 100644 --- a/wiringPi/wiringPi.c +++ b/wiringPi/wiringPi.c @@ -1,7 +1,7 @@ /* * wiringPi: * Arduino look-a-like Wiring library for the Raspberry Pi - * Copyright (c) 2012-2025 Gordon Henderson and contributors + * Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors * Additional code for pwmSetClock by Chris Hall * * Thanks to code samples from Gert Jan van Loo and the diff --git a/wiringPi/wiringPi.h b/wiringPi/wiringPi.h index 819a58f..07cd258 100644 --- a/wiringPi/wiringPi.h +++ b/wiringPi/wiringPi.h @@ -1,7 +1,7 @@ /* * wiringPi.h: * Arduino like Wiring library for the Raspberry Pi. - * Copyright (c) 2012-2025 Gordon Henderson + * Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors *********************************************************************** * This file is part of wiringPi: * https://github.com/WiringPi/WiringPi/ diff --git a/wiringPi/wiringPiI2C.c b/wiringPi/wiringPiI2C.c index 95131c3..6ec1789 100644 --- a/wiringPi/wiringPiI2C.c +++ b/wiringPi/wiringPiI2C.c @@ -1,7 +1,7 @@ /* * wiringPiI2C.c: * Simplified I2C access routines - * Copyright (c) 2013-2024 Gordon Henderson and contributors + * Copyright (c) 2013–2019 Gordon Henderson; 2019–2026 Contributors *********************************************************************** * This file is part of wiringPi: * https://github.com/WiringPi/WiringPi/ diff --git a/wiringPi/wiringPiI2C.h b/wiringPi/wiringPiI2C.h index 112257a..22df490 100644 --- a/wiringPi/wiringPiI2C.h +++ b/wiringPi/wiringPiI2C.h @@ -1,7 +1,7 @@ /* * wiringPiI2C.h: * Simplified I2C access routines - * Copyright (c) 2013-2024 Gordon Henderson and contributors + * Copyright (c) 2013–2019 Gordon Henderson; 2019–2026 Contributors *********************************************************************** * This file is part of wiringPi: * https://github.com/WiringPi/WiringPi/ diff --git a/wiringPi/wiringPiSPI.c b/wiringPi/wiringPiSPI.c index e182523..840f175 100644 --- a/wiringPi/wiringPiSPI.c +++ b/wiringPi/wiringPiSPI.c @@ -1,7 +1,7 @@ /* * wiringPiSPI.c: * Simplified SPI access routines - * Copyright (c) 2012-2025 Gordon Henderson and contributors + * Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors *********************************************************************** * This file is part of wiringPi: * https://github.com/WiringPi/WiringPi/ diff --git a/wiringPi/wiringPiSPI.h b/wiringPi/wiringPiSPI.h index d60b064..aa15aa6 100644 --- a/wiringPi/wiringPiSPI.h +++ b/wiringPi/wiringPiSPI.h @@ -1,7 +1,7 @@ /* * wiringPiSPI.h: * Simplified SPI access routines - * Copyright (c) 2012-2025 Gordon Henderson and contributors + * Copyright (c) 2012–2019 Gordon Henderson; 2019–2026 Contributors *********************************************************************** * This file is part of wiringPi: * https://github.com/WiringPi/WiringPi/