Commit 53231f31 authored by Your Name's avatar Your Name
Browse files

Merge branch 'lslder2021'

parents a2df09ab 5716363e
LSLBASE=../labstreaminglayer/build/install
CXXFLAGS+=-Wall -Wno-sign-compare -I$(LSLBASE)/include
LDFLAGS+=-L$(LSLBASE)/lib -llsl32 -lwiringPi -lboost_system -lpthread
LDFLAGS+=-L$(LSLBASE)/lib -llsl32 -lpigpio -lboost_system -lpthread
LDLIBS+=-lzmq -lpthread -lboost_system -lboost_regex -lboost_program_options
#INCLUDE+=RS-232
......@@ -10,8 +10,7 @@ CXXFLAGS+=-Wall -std=c++11
CXX=g++
CC=g++
TARGETS=lslder_1chan lslder_4chan lslder_8chan sendrand lslder_4chan_proto
TARGETS=lslder_1chan lslder_4chan lslder_8chan sendrand
all: $(TARGETS)
#lslder : CPPFLAGS+=-DLSLDER_8CHAN
......@@ -34,6 +33,7 @@ lslder_1chan.o: lslder_uni.cc
sendrand: sendrand.cc
lslder_4chan_proto: lslder_4chan_proto.cc
lslder_4chan_proto: LDFLAGS+=-lwiringPi
clean:
rm -f $(TARGETS) *.o
......
#include "led.h"
#include <wiringPi.h>
#include <pigpio.h>
#include <stdlib.h>
#include <unistd.h>
......@@ -16,7 +16,7 @@ void initleds(int _nled, const int *_ledgpio)
ledgpio = _ledgpio;
for (int i=0; i<nled; i++)
{
pinMode(ledgpio[i], OUTPUT);
gpioSetMode(ledgpio[i], PI_OUTPUT);
}
playleds();
}
......@@ -63,5 +63,10 @@ void setled(int lednr, int value)
else
bit = 0;
digitalWrite(ledgpio[lednr], bit);
int r= gpioWrite(ledgpio[lednr], bit);
if (r < 0)
{
perror("gpioWrite");
exit(1);
}
}
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
No preview for this file type
......@@ -2,28 +2,34 @@
//
// LSL Digital Event Recorder
//
// This program offers a maximum of eight LSL event streams, each triggered by positive edges on
// raspberry pi GPIO digital inputs. Visual feedback is provided bij eight LEDs.
// The stream type is "Digital Events - $HOSTNAME", where HOSTNAME is the ip hostname of
// the raspberry. This is to uniquely identify devices on the network.
// The data sent with the events is an int8 with value 1, with 1 indicating a rising edge.
// Falling edges can be sent with a 0 value. However this is not implemented in this
// program.
// This program offers a maximum of eight LSL event streams, each triggered by
// positive edges on raspberry pi GPIO digital inputs. Visual feedback is
// provided bij eight LEDs. The stream type is "Digital Events - $HOSTNAME",
// where HOSTNAME is the ip hostname of the raspberry. This is to uniquely
// identify devices on the network. The data sent with the events is an int8
// with value 1, with 1 indicating a rising edge. Falling edges can be sent with
// a 0 value. However this is not implemented in this program.
//
// Dependencies: labstreaminglayer C++ and wiringPi
// Dependencies: labstreaminglayer C++
// CHANGES
// GW/20180716 initial version for 8-channel LSL Digital Event Recorder
// GW/20210210 remove deprecated wiringPi and use pigpio instead
// TODO: use ISR tick for debounce timing
// TODO: add support to register falling edges
#include <lsl_cpp.h>
#include <stdlib.h>
#include <unistd.h>
#include "led.h"
#include <chrono> // std::chrono::seconds
#include <cstring>
#include <iostream>
#include <lsl_cpp.h>
#include <mutex>
#include <pigpio.h>
#include <sched.h>
#include <signal.h>
#include <stdlib.h>
#include <thread> // std::this_thread::sleep_for
#include <chrono> // std::chrono::seconds
#include <wiringPi.h>
#include "led.h"
#include <unistd.h>
#define DEBUG
......@@ -33,7 +39,7 @@ using namespace lsl;
// 1 channel portable version without LEDs
const int ngpio = 1;
const int gpioinp[ngpio] = { 8 };
const int gpioinp[ngpio] = {8};
const int default_debouncetime = 100;
......@@ -46,11 +52,11 @@ const int nled = 0;
// 4-chan version with 4 LEDs
const int ngpio = 4;
const int gpioinp[ngpio] = { 24, 23, 18, 15 };
const int gpioinp[ngpio] = {15, 18, 23, 24};
const int default_debouncetime = 0;
const int ledgpio[] = { 5, 14, 3, 2 };
const int ledgpio[] = {2, 3, 14, 5};
const int nled = 4;
#endif
......@@ -59,172 +65,188 @@ const int nled = 4;
// 8-chan version with 8 LEDs
const int ngpio = 8;
const int gpioinp[ngpio] = { 12, 7, 8, 25, 24, 23, 18, 15 };
const int gpioinp[ngpio] = {12, 7, 8, 25, 24, 23, 18, 15};
const int default_debouncetime = 0;
const int ledgpio[] = { 21, 20, 16, 13, 5, 14, 3, 2 };
const int ledgpio[] = {21, 20, 16, 13, 5, 14, 3, 2};
const int nled = 8;
#endif
int ledtime=2; // in 1/100 sec., see infinite loop in main()
volatile int ledtimer[ngpio] = { 0, };
int ledstatus[ngpio] = { 0, };
const int maxgpio = 54; // BCM chip has 54 GPIO
int gpiomap[maxgpio];
int debouncetimes[ngpio] = { 0, };
volatile int debouncetimer[ngpio] = { 0, };
void init_gpiomap() {
// map BNC input channel wiring 0..ngpio-1 to BCM GPIO
for (int bnc_input = 0; bnc_input < ngpio; bnc_input++) {
int bcmgpio = gpioinp[bnc_input];
gpiomap[bcmgpio] = bnc_input;
}
}
int ledtime = 2; // in 1/100 sec., see infinite loop in main()
volatile int ledtimer[ngpio] = {
0,
};
int ledstatus[ngpio] = {
0,
};
int debouncetimes[ngpio] = {
0,
};
volatile int debouncetimer[ngpio] = {
0,
};
#ifdef DEBUG
volatile int interrupt_count[ngpio] = { 0, };
volatile int interrupt_count[ngpio] = {
0,
};
#endif
stream_outlet *outlet[ngpio];
std::mutex lsl_mutex;
typedef char int8;
void gpioInterrupt(int channel)
{
if (debouncetimer[channel])
volatile int run = 1;
void stop(int signum) { run = 0; }
void gpioISR(int gpio, int level, uint32_t tick) {
int bnc_input = gpiomap[gpio];
if (level == 2) // timeout call
return;
if (debouncetimer[bnc_input])
return;
else
debouncetimer[channel] = debouncetimes[channel];
debouncetimer[bnc_input] = debouncetimes[bnc_input];
static int edge = 1;
std::lock_guard<std::mutex> guard(lsl_mutex);
#ifdef DEBUG
std::cout
<< "Interrupt on channel " << channel
<< " (GPIO " << gpioinp[channel] << ")"
<< std::endl;
std::cout << "Interrupt on bnc_input " << bnc_input << " (GPIO "
<< gpioinp[bnc_input] << ")" << std::endl;
#endif
static int edge=1;
std::lock_guard<std::mutex> guard(lsl_mutex);
outlet[channel]->push_sample(&edge);
ledtimer[channel]=ledtime;
outlet[bnc_input]->push_sample(&edge);
ledtimer[bnc_input] = ledtime;
#ifdef DEBUG
interrupt_count[channel]++;
std::cout << channel << " (count=" << interrupt_count[channel] << ")" << std::endl;
interrupt_count[bnc_input]++;
std::cout << bnc_input << " (count=" << interrupt_count[bnc_input] << ")"
<< std::endl;
#endif
}
void handleLeds()
{
for (int i=0; (i<ngpio) && (i<nled); i++)
{
void handleLeds() {
for (int i = 0; (i < ngpio) && (i < nled); i++) {
if (ledtimer[i] > 0) {
if (!ledstatus[i]) {
setled(i,1);
ledstatus[i]=1;
setled(i, 1);
ledstatus[i] = 1;
}
ledtimer[i]--;
}
else {
if (ledstatus[i]) {
setled(i,0);
ledstatus[i]=0;
setled(i, 0);
ledstatus[i] = 0;
}
}
}
}
int rtpriority(int n) {
struct sched_param sched;
void gpioISR_0()
{
gpioInterrupt(0);
}
void gpioISR_1()
{
gpioInterrupt(1);
}
memset(&sched, 0, sizeof(sched));
void gpioISR_2()
{
gpioInterrupt(2);
}
void gpioISR_3()
{
gpioInterrupt(3);
}
if (n > sched_get_priority_max(SCHED_RR))
sched.sched_priority = sched_get_priority_max(SCHED_RR);
else
sched.sched_priority = n;
void gpioISR_4()
{
gpioInterrupt(4);
return sched_setscheduler(0, SCHED_RR, &sched);
}
void gpioISR_5()
{
gpioInterrupt(5);
}
int main(int argc, char *argv[]) {
init_gpiomap();
void gpioISR_6()
{
gpioInterrupt(6);
}
if (rtpriority(99) < 0) {
perror("rtpriority");
return 1;
}
void gpioISR_7()
{
gpioInterrupt(7);
}
// configure input channels
int r = gpioInitialise(); // use Broadcom pin numbering
if (r < 0) {
perror("gpioInitialise");
return 1;
}
typedef void(*gpioISR)();
gpioSetSignalFunc(SIGINT, stop);
gpioSetSignalFunc(SIGABRT, stop);
gpioISR ISR[] = { gpioISR_0, gpioISR_1, gpioISR_2, gpioISR_3,
gpioISR_4, gpioISR_5, gpioISR_6, gpioISR_7 };
printf("Press control C to stop.\n");
int main(int argc, char* argv[]) {
piHiPri(99); // shortcut for running at real time priority
initleds(nled, ledgpio);
// configure inputs
wiringPiSetupGpio();
for (int i = 0; i < ngpio; i++) {
int bcmgpio = gpioinp[i]; // BCM GPIO number
//if (gpioSetMode(bcmgpio, PI_INPUT) < 0) {
// perror("gpioSetMode");
// return 1;
// }
initleds(nled, ledgpio);
debouncetimes[i] = default_debouncetime;
for (int i=0; i<ngpio; i++)
{
pinMode(gpioinp[i], INPUT);
pullUpDnControl(gpioinp[i], PUD_UP);
const int timeout_ms = 10000;
// The 4N35 optocoupler in the input circuit inverts the signal, we want
// to detect rising edges in the input signal, so here we program
// FALLING_EDGE.
if (gpioSetISRFunc(bcmgpio, FALLING_EDGE, timeout_ms, gpioISR) < 0) {
perror("gpioSetISRFunc");
return 1;
}
if (gpioSetPullUpDown(bcmgpio, PI_PUD_UP) < 0) {
perror("gpioSetMode");
return 1;
}
for (int i=0; i<ngpio; i++) {
debouncetimes[i] = default_debouncetime;
#ifdef DEBUG
std::cout << "Set IRQ handler for gpio " << bcmgpio << std::endl;
#endif
}
char hostname[255];
gethostname(hostname,255);
for (int i=0; i<ngpio; i++)
{
gethostname(hostname, 255);
for (int i = 0; i < ngpio; i++) {
// make a new stream_info and open an outlet with it
char info_name[255];
sprintf(info_name, "Digital Events %d", i);
char info_type[255+18];
sprintf(info_type,"Digital Events @ %s",hostname);
char info_type[255 + 18];
sprintf(info_type, "Digital Events @ %s", hostname);
stream_info info(info_name, info_type, 1, lsl::IRREGULAR_RATE,
lsl::cf_int8,"Raspberry Pi Digital Event Recorder");
lsl::cf_int8, "Raspberry Pi Digital Event Recorder");
outlet[i] = new stream_outlet(info);
}
// The 4N35 optocoupler in the input circuit inverts the signal, we want to
// detect rising edges in the input signal, so here we program INT_EDGE_FALLING.
for (int i=0; i<ngpio; i++)
{
wiringPiISR(gpioinp[i], INT_EDGE_FALLING, ISR[i]);
}
// do this forever
while(true) {
while (run) {
std::this_thread::sleep_for(std::chrono::milliseconds(10));
handleLeds();
for (int i=0; i<ngpio; i++) {
for (int i = 0; i < ngpio; i++) {
if (debouncetimer[i] > 0)
debouncetimer[i]--;
}
}
gpioTerminate();
return 0;
}
No preview for this file type
No preview for this file type
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment