🔍 Simple bare-metal logic analyzer for the Pi.
C Other
Permalink
Failed to load latest commit information.
images
src
.gitignore
Makefile
README.md
memmap
proposal.md

README.md

Logic analyzer

I made the Raspberry Pi into a simple stand-alone logic analyzer. It displays a running view of the last second of input on a few GPIO pins of your choice. (You can adjust the pins displayed easily in analyzer.c, line 125, and the time window at line 61.)

The analyzer can record for thirty seconds, then it will throw out the samples and start recording again. You can also configure it to go into a STOP mode after 30 seconds (see sampler_update_log in sampler.c) but then you'd have to restart to begin recording again, since the analyzer doesn't take user input right now. That STOP/REC state system is intended to be used with some kind of input device in an expanded version of the logic analyzer.

The sampler records with a frequency you can define in sampler.c (SAMPLING_FREQ). Testing indicates you can go between 1Hz and 100KHz but not above (default is 10KHz); that's probably fixable, since the timer maximum is 1MHz, but needs to be diagnosed.

I did a weak verification of the sampling frequency, which you can replicate by running make EXTRAFLAGS=-DVERIFY to enable the time verification. The sampler will then send a list of times between samples over serial after 30 seconds. As you can see, we have 100 microseconds between samples when we run at 10KHz:

A further step would be to attach a signal generator to the logic analyzer, or even do a loopback and use another timer on the same machine to generate signals, and verify that we sample properly.

Brief overview of the directory tree under src/:

  • Most project-specific code is in the root:
    • analyzer.c is the GUI and render loop
    • sampler.c is the sampling engine and interrupt handling.
    • systimer.c is a driver I wrote for the more precise (and, in my opinion, easier) GPU/system timer, incl. interrupt support
    • ringbuf.c is a general ringbuffer-of-unsigned-ints library which operates on a pointer to the ringbuffer.
    • mouse.c contains abortive mouse support.
  • util/ and printf/ contain the assignment library with small changes.
    • I rewrote timer.c to use structs while I was evaluating how to do sampling.
  • gpu/ contains abortive GPU support.
  • gfx/ contains slightly modified assignment framebuffer graphics driver (including line-drawing extension)
    • I figured out DMA and changed fb.c to use DMA for screen clearing, since I needed very fast screen updates for the 'oscilloscope' display

I spent a lot of time on random peripherals (GPU, mouse) which don't really work and are rather difficult to debug. The GPU driver (based on Peter Lemon's) can clear the screen and allocate a GPU framebuffer (using, I think, a different method than ours), but doesn't do much else. The mouse driver has a similar problem: mice need to get a signal from the computer before doing much, unlike keyboards, and we've only worked in the receive direction before.

A few things which came out well and which I'm proud of:

  • The whole sampling system: timer driver, timer interrupts, ring buffer which both interrupts and main thread touch, and then a permanent log that only the main thread uses
  • DMA for screen clear was not too difficult and was effective.
  • Code style and organization seem pretty good. Modules are well-defined and have nice interfaces.

The major next step would be to add support for some input device. Keyboard would be easier, but mouse is more natural, in my opinion. Then you could pause and stop and restart recording, first of all, but you could also pan and zoom in the sampling view. Replaying into a pin is another interesting direction. I have most of the infrastructure to do this in the code, but it's not exposed.