In my library/Google trawl I turned up EEGMIR which is to be found here. This uses regular C code to run the IIR filters, the implication is this is a digital implementation of analogue filters, probably achieved by transforming the s plane to the z plane and predistorting the response. This would save me heroic amounts of tweaking analogue filters. If I could run it on a Raspberry Pi, i could get my Mind Mirror 1 LED display by extending the display code and using the GPIO.
But first I need to characterise the program, compile it on the PI and get it working. And the program is 14 years old… I’m not a C guru though I have used the language, not professionally but in its bastardised form for the Arduino, and I’m not a DSP guru either. So I’m hopelessly way out of my depth. I do like the way Jim Peters took an interesting approach to the amplitude display of the bands, downconveritng the bandpass with fc to make a direct-conversion receiver to DC. When you can do this with an IQ demodulator it works better than the amateur radio hardware implementation. But first things first. Does it compile?
Compiling eegmir on the Pi
I get a new Raspberry Pi B+ V2, and a copy of jessie-lite. If you are starting form scratch use a regular Pixel Jessie install. it’s a graphical program though it looks ugly, so you need the Xwindows system.
sudo apt-get update
sudo apt-get upgrade
Follow
[GUIDE] Raspbian Lite with PIXEL/LXDE/XFCE/MATE/Openbox GUI
to install Pixel. And X. That’s why you should have started with a full install. EEGMIR is a graphical display program, nearly everything else I use Pi for is command line. I don’t normally bother with the desktop on a Pi because I run these guys headless.
do ./mk a
compiler screams, I need something called SDL. Due to the age of the program SDL2 doesn’t work. Install SDL 1.2
sudo apt-get install libsdl1.2-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev
now ./mk a grizzles thusly
=== page_bands.c
tmp-linux/page_bands.c: In function ‘draw_signal’:
tmp-linux/page_bands.c:335:4: error: label at end of compound statement
no_more_data:
^
FAILED
Hmm. I’m in trouble now, I look at Jim Peters’ code page_bands.c and he makes a leap out of some nested loops
//
// Draw the signal area
//
static void
draw_signal(PageBands *pg, int xx, int yy, int sx, int sy, int tsx) {
int tb= 1; // Timebase -- samples/pixel
int a, b;
[...]
if (oy0 < sy && oy1 >= 0) {
if (oy0 < 0) oy0= 0;
if (oy1 >= sy) oy1= sy-1;
vline(xx + ox, yy+oy0, oy1-oy0+1, pg->c_sig1);
}
}
}
no_more_data: // <- COMPILER MOANS ABOUT THIS
}
}
I’m in pretty deep trouble here. I don’t really understand what’s going on. I invoke the spirit of the Big G on the error message and I am educated like so
case 5:
// here you need to add statement
//if you don't want to do anything simple break statement will work for you
break;
to lob in a break statement after that no-more-data: label. I am hacking, I’m not proud of it but sometimes you have to try and keep the wheels running to make progress 😉 . Compiler is now happy with a modest amount of bellyaching
=== fidlib/fidlib.c In file included from fidlib/fidlib.c:622:0: fidlib/fidmkf.c:151:1: warning: conflicting types for built-in function ‘csqrt’ csqrt(double *aa) { ^ fidlib/fidmkf.c:175:1: warning: conflicting types for built-in function ‘cexp’ cexp(double *aa) { ^
I throw caution to the winds and run the program. It now comes up but spits bricks on the command line
pi@raspieeg:~/eegmir/eegmir-0.1.12 $ ./eegmir eegmir: Unable to open serial device: /dev/ttyS0
maybe need to detach ttyS0. You do that with Raspi-config, turn off terminal output but keep the hardware enabled, Still moans about ttyS0. That’s because on the Pi this should be ttyAMA0
I change ttyS0 to ttyAMA0 in eegmir.cfg
it now responds, though glacially slowly on Xwindows, to the F2 (MM) and F3 (display test) and F4 (exponential frequency map) and F10 (jitter calc). I take the hit and run it on a real composite video display. My cable was a camcorder cable so I needed to use the right audio cable. Ain’t Google marvellous.
Responsiveness is much improved. My addition of the break statement has not obviously borked the program. In Googling there was talk of some versions of gcc letting the empty statement after a label pass and some versions getting shirty, maybe this was different 14 years ago.
I observed the lack of settling to zero on the IIR filters in the low frequencies, which corroborates the feeling i got reading about the effects of truncation of the filter coefficients being worse close to the sampling frequency and close to zero. After all, I can absolutely dead-certain guarantee that the input is digital silence, because there is no input.
The jitter test screen on F10 moans at me that it can’t work out the jitter. Can’t really argue with that, because there is no input. I need to go fix that next.
Pressing F11 gives me
So I jack a pair of cans across the audio output of the Pi and I get to hear what sounds to me like 1kHz tone
Github
This program is on Github at
https://github.com/pine-marten/eegmir
Jim Peters GPL2 it so I have retained the same license on Github
Conclusion – it works in principle
So far I surmise that I haven’t mortally wounded the program by tossing in that arbitrary break statement and that it will run on a Pi. I have no idea of if I have enough MIPS for a decent performance. A Raspberry Pi 2 has 4,744 MIPS whereas a 2003 vintage Pentium 4 had 9,726 MIPS, since I am using a Pi B+ which is less than the pi 2 I may be short of processing grunt. But for that I need a signal.
Rummaging around looking for the HDMI to VGA adapter I had in the loft I found a Pi 2 sitting unloved, so I swapped the B+ for a Pi2 for an instant hardware upgrade. There is a comparison of the performance of the B+ and the 2 here. The program is more responsive now, so I do the whole
sudo apt-get update
sudo apt-get upgrade
sudo apt-get dist-upgrade
sudo apt-get clean
and then recompile, this time it recompiles all the program components, so I figure something changed under the hood to get all those four cores working for me. I get the same griping about the conflicting types.
I find out how to boost the bar gain, to take a better look at that suspected truncation noise in the low frequency filters. That’s the b key followed by a number
This doesn’t really trouble me, that’s lifted by 100 times. I will do gain control in the analogue domain and the Mind Mirror did not eq individual channels or do any other levelling other than master gain. But it shows that the 0.75Hz Mind mirror channel could be ‘interesting’ to add. Truncation noise seems to get worse as you get to fs/2 and to 0. fs/2 is 128 Hz so I am well away from that, I could benefit from halving fs, and is something to bear in mind in the hardware design, and testing if the software will adjust.
You need the C equivalent of an assembler NOP 🙂 I wondered if you could just stick a “;” after the label as a null statement and this seems to imply that you can:
http://stackoverflow.com/questions/9730893/in-c-why-do-you-need-a-statement-after-a-goto-label
“break;” probably does exactly the same thing though.
( Aah, stackoverflow, do you remember when we had to actually read manuals and standards? )
Thank you – that makes more sense now. I have replaced break with the semicolon, to me break; implies get me the hell out of this loop now, which could lead to nasty side-effects. Since I am in thousand-monkeys mode on this prog rather than understanding it minimal changes get my vote.
> stackoverflow, do you remember when we had to actually read manuals and standards?
hehe, and actually learn things properly too 😉 I really need to learn c properly one day!
Using the little known “-S” option on the gcc command one can see the generated assembler. From a quick test a line like:
end_proc: ;
generates the following assembler:
.L4:
nop
and there’s your NOP 🙂