RichardNeill.org

PulseBlaster Linux Driver, utilities and parser

Introduction

The Spincore PulseBlaster is a Programmable TTL Pulse Generator / Digital Word Generator and Timing Engine. We have written a Linux driver for it, some utilities, and a parser/compiler/simulator. Everything is Free Software, under GNU GPL.

Linux kernel driver: this works under 3.8, and we are currently working to get it accepted upstream. It creates entries in /sys, under /sys/class/PulseBlaster/, and has a very simple interface: to program the device, just cat the binary into the the program interface, and to start/stop/arm, just echo a 1 into the start/stop/arm interface.

Utilities: pb_utils contains a set of C-programs which can control the PulseBlaster, assemble "Very long instruction word" (VLIW) files, and are useful for diagnostics, testing and debugging.

Parser: pb_parse is a high-level parser for the PulseBlaster. It reads a high-level PBSRC format, and outputs VLIW for pb_asm. It can also simulate the PulseBlaster, writing a virtual "piano-roll", or to a wavefile analyser (e.g. GTKWave. It can prove program correctness, because the PulseBlaster is not Turing-Complete. [This also facilitates a "hack" of combining 1-3 ordinary parallel-ports into a "Poor-man's PulseBlaster", albeit rather slow and jittery.]

Overview: Source-file (.pbsrc) -> parser (pb_parse) -> assembly file (.vliw) -> assembler (pb_asm) -> binary file (.bin) -> programmer (pb_prog) -> pulseblaster hardware (/sys/class/pulseblaster) -> trigger (pb_start).

Example 1: This is an example of the type of program one can write, which is actually useful: pixel_characterise.pbsrc, hawaii.h, macros.pbsrc, clock_calc.php, README.txt

Example 2: This is a demonstration of the simulation output (piano-roll mode). The source is a simple 2-of-5 walking LEDs program (walking_5leds_5Hz.pbsrc).

Driver (Linux kernel, pulseblaster.ko)

This supports the PulseBlaster SP1 PB24-100-32k board, with PCI vendor/device ID of 0x10e8:0x5920.
The newer SP2 boards have the same vendor id (0x10e8) and device IDs (0x8879 or 0x8852; both being functionally identical).
[Although we haven't an SP2 board to test with, if the protocol is the same, it will suffice to add the IDs into the pb_pci_tbl struct in PulseBlaster.c.]

The kernel module, pulseblaster.ko, creates entries in /sys/class/pulseblaster/pulseblaster0/ as follows:

  • stop, start, arm, continue  -  echo a "1" to this to trigger the corresponding action.
  • program  -  write a raw binary file here to program the PulseBlaster.

pb_utils (low-level control and debugging)

  • pb_asm, pb_prog  -  assemble a VLIW file into binary and program it into the PulseBlaster.
  • pb_stop, pb_start, pb_cont, pb_arm, pb_stop-arm  -  stop/start/arm/continue/stop-and-rearm the PulseBlaster.
  • pb_init, pb_zero  -  directly set the PulseBlaster's outputs.
  • pb_vliw  -  generates an example/demo VLIW file. (see also vliw (5))
  • pb_check  -  check lspci for the PulseBlaster hardware.
  • pb_identify_output  -  identify a particular hardware output and check phase.
  • pb_freq_gen.sh  -  generate a square wave of a desired frequency on selected bits.
  • pb_manual  -  manually, interactively, control the PulseBlaster outputs. Useful for debugging whatever it's connected to.

pb_parse (high-level parser and simulator)

These are the features of pb_parse. It is basically a complicated pre-processor, that fakes as many desired features as possible (eg bit-at-a-time instructions and macros).

  • Outputs and arguments may be specified in binary, hex, or base-10.
  • Lengths may be specified in ticks, or in units of ns,us,ms,s,ks,min...weeks.
  • Where an argument is irrelevant, a '-' is used to make this explicit.
  • Labels can be used, instead of numeric addresses.
  • Comments are: '//', '/* ... */'.
  • Support for #include, #define [#what, #default:, #if, #ifnot].
  • Scientific/experimental parameters can be easily varied with -D (and #if/#ifnot).
  • Executable includes (#execinc) allow dynamic code generation and complex calculations.
  • Outputs can be specified as bitwise changes to the previous values (or SAME).
  • Inlined #macros (with parameter substitution), almost acting like functions.
  • Use of #set simplifies use of active-low logic on the peripheral.
  • Debugging features: #assert, #hwassert, #echo, #endhere.
  • "Do what I mean" fixes for infelicities in the instruction set:
    • calculates ARG for longdelay if specified as 'auto'
    • promotes cont or demotes longdelay if length is out of range.
    • zeroloop: loop (0) converted to goto (addr_of(endloop)+1).
    • opcode macros: __call/goto/return/loop/endloop can appear instantaneous.
  • Case-sensitive (except opcode-names). Alternate opcode mnemonics (eg GOTO vs BRANCH).
  • Allows STOP to be overloaded (set outputs). Adds NOP.
  • VLIW-reordering: opcode,arg may be written before/inside/after out...len, for clarity.
  • Mathematical operators: *,-,+,/,%,(,) Bitwise operators: |,&,~,^,<<,>>
  • Comparison operators: ==,!=,<,>,<=,>= Logical: &&,||,!,?,: Error-control: @
  • Detailed error checking, with helpful messages. Ensures that all instructions are valid.
  • Simulation of the hardware, to verify the program. Options:
    • Optimised simulation (full proof of program correctness),
    • Output on virtual LEDs, parallel ports, VCD file, and target-simulation logfile.
    • Real-time, measurement, single-step, or manual triggering.
  • Output Formats: pulseblaster (.vliw, .bin), simulation (.pbsim, .vcd), byte-stream.

Because the PB isn't Turing-Complete, the advanced hacks must be evaluated at compile-time, not run-time. For more details, see the man-page and some of the examples.
As an example of the fun to be had with preprocessor abuse, this contrived line is legal syntax, in which, #define, #ifnot, and bit_flip() are all effected at compile-time.
#define JULY #ifnot(HERRING) bit_flip(PENGUIN) goto ANTARCTICA ALL_SUMMER

VLIW format (very long instruction word)

The basic human-readable "assembly" format is vliw. This is converted (by pb_asm) to a raw (binary) file, which can be loaded with pb_prog. The vliw format consists of 4 columns (delimited by whitespace and with an optional //comment), in the order: Output, Opcode, Arg, Length. Output and Length are numbers (dec/hex). Opcode is a string eg "cont" or "goto". Arg is either a number, or a "-" where it is not required. Vliw programs are not especially easy to write: for example, time-units must be in ticks, addresses must be literal, and there is no support for macros.

These are the details of the PulseBlaster opcodes. Some specific details are for loops, long-delay, wait, and latencies.

Triggering (hardware and software) behaviour is described here.

Here is a simple example.vliw file; there are many more in the vliw_examples directory.

PBSRC format (pulseblaster source)

The pbsrc language and associated compiler abstracts away some of the quirks of the device, and adds (or fakes) extra features such as bit-at-a-time instructions. [It will emit an error or a warning in cases where these are used inappropriately.]

For example, loop (n) may have n=1 and n=0, and cont<-->longdelay are implicitly promoted/demoted. It's also possible to have executable-includes, a hack which allows much greater flexibility of dynamically-generated code.

The parser can also simulate the PulseBlaster, which allows for program validation (will it halt or run forever? does it ever exceed the maximum stack depths?) and full or partial simulation. The output data can be in pbsim format (useful for hawaiisim), or in vcd (value change dump) format for GTKWave. It can also write directly to a parallel port (for the "poor-man's PulseBlaster").

Here is an example.pbsrc file; there are many more in the pbsrc_examples directory.

Installation

  • Prerequisites: for pb_parse, install PHP-cli (at least version 5.2). pb_utils just needs GCC.
  • To install, simply: make && sudo make install. Then run, for example pb_freq_gen.
  • In the pb_parse directory, run make examples Then run, for example pb_test-pbsrc-walk5.
  • To install just one of the driver, pb_utils, or pb_parse, just run make && sudo make install in the corresponding subdirectory.
  • This is Free Software released under the GNU GPL v3+ (except the kernel driver which is v2). Please feel free to take it, modify it, package it etc.
  • Authors: Richard Neill (pb_utils, pb_parse) and Michael Brown (pulseblaster.ko). Do ask if you would like further information and assistance.

Notes

The implementation of the PulseBlaster is unusual: it runs pulse programs on an internal FPGA. This means that it will keep running even during a reboot of the host!
Also, the language is not Turing-complete: this makes it very predictable, but adds certain limitations. pb_parse gets around a few of them.

We also created some custom additions: external clock input and triggering via an RS-232 port: details.

Bugs: pb_parse is a very long PHP program, containing some 5368 lines and 130 Regular Expressions, and needing significant RAM for larger programs. It hasn't yet fulfilled Zawinski's law, though the -M option is reserved. Also, as the PBSRC language is based on VLIW, it uses whitespace as the delimiter, which, with hindsight, isn't ideal

This was originally written as part of my PhD Infrared Camera system. It should be applicable for wider usage.
A real-world example of the system is in hawaii_characterise.sh distributed in the hawaii_sensor section: PulseBlaster code is dynamically generated to run a series of experiments on a detector.

Download

pulseblaster.tgz
GIT repository

Documents

Some selected files, from the tarball:
README.txt
vliw.5
pbsrc.5
pbsim.5
pb_utils.1
pb_parse.1
pb_freq_gen.1
pb_manual.1
pb_parport-output.1

Navigation

Return to all programs, site home.