the GPIO subsystem on the Raspberry allows to set pins for "interrupt" the created subsystem file becomes readable on any level change.
Raspberry GPIO utilityUnfortunately I could not coerce tcl to ignore the eof condition. So I expanded the sample c programm to handle multiple pins set up for interrupt notice to be watched over and handed in to a tcl file input.
the helper will first iterate over all configured inputs and report their current state. then one line will be output for every event seen. <pin>:<state> which fits in nicely with the tcl event model.
Useage example ( here the gpio 23, 24 and 25 ) :
# config input:
proc Uevent fd {
set line [gets $fd]
puts stderr line:>>$line<<
switch -- $line \
23:0 {
hands right
} 23:1 {
hands right 0
} 24:0 {
hands left
} 24:1 {
hands left 0
} 25:0 {
puts stderr Release
} 25:1 {
set ::stop [ clock milliseconds ]
incr ::cont
} default {
}
}
set fd [ open "| ./gpioirq 23 24 25" RDONLY ]
fconfigure $fd -buffering none
fileevent $fd readable [list Uevent $fd]
Then create a fileevent readable for $fd.
fileevent $fd readable [list Uevent $fd]
./gpioirq.c slightly expanded from an example give on the gpio project page.
// adapted from an example.
// i2016 Uwe Klein Habertwedt
#include <stdio.h>
#include <poll.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#define GPIO_FN_MAXLEN 32
#define POLL_TIMEOUT 1000
#define RDBUF_LEN 5
int main(int argc, char **argv) {
char fn[GPIO_FN_MAXLEN];
int fd[argc],ret, arg;
struct pollfd pfd[argc];
char rdbuf[RDBUF_LEN];
memset(rdbuf, 0x00, RDBUF_LEN);
memset(fn, 0x00, GPIO_FN_MAXLEN);
if(argc<2) {
printf("Usage: %s <GPIO>\nGPIO must be exported to sysfs and have enabled edge detection\n", argv[0]);
return 1;
}
for (arg=1;(arg<argc);arg++) {
snprintf(fn, GPIO_FN_MAXLEN-1, \
"/sys/class/gpio/gpio%s/value", argv[arg]);
fd[arg]=open(fn, O_RDONLY);
if(fd[arg]<0) {
perror(fn);
return 2;
}
pfd[arg].fd=fd[arg];
pfd[arg].events=POLLPRI;
ret=read(fd[arg], rdbuf, RDBUF_LEN-1);
if(ret<0) {
perror("read()");
return 4;
return 4;
}
printf("%s:%s", argv[arg],rdbuf);
}
fflush(stdout);
while(1) {
memset(rdbuf, 0x00, RDBUF_LEN);
for (arg=1; arg<argc;arg++) {
lseek(fd[arg], 0, SEEK_SET);
}
ret=poll(&pfd[1], argc-1, POLL_TIMEOUT);
if(ret<0) {
perror("poll()");
close(fd);
return 3;
}
if(ret==0) {
// printf("timeout\n");
continue;
}
for (arg=1; arg<argc;arg++) {
if (pfd[arg].revents) {
ret=read(fd[arg], rdbuf, RDBUF_LEN-1);
printf("%s:%s", argv[arg], rdbuf);
fflush(stdout);
}
}
if(ret<0) {
perror("read()");
return 4;
}
}
close(fd);
return 0;
}