-
Notifications
You must be signed in to change notification settings - Fork 4
Sequencer Domain Specific Language Tutorial
The FPE orchestrates CCD clocking and data acquisition via a series of clock sequences and a program that emits them in the appropriate order. The sequencer language provides a compact way to create and document the sequences and program.
To upload the FPE to the Observatory Simulator server, use the upload_fpe_program
script described in the tessfpe
documentation.
The sequencer language uses classic C-style comments.
/* This is a comment */
For convenience, the sequencer language allows you to compute constants and define parameters at compile time. Constant expressions are classic Fortran-style integer expressions using "+-*/()" interpreted left to right with traditional precedence. Statements like:
parameter rows = 2048;
parameter buffer_rows = 10; /* top and bottom */
parameter physical_rows = rows + 2 * buffer_rows;
parameter columns = 512;
parameter prescan = 11;
parameter physical_columns = prescan+columns;
...define named constant parameters. You may use a named parameter or an expression wherever you'd use a numeric constant.
A typical sequence block looks like:
sequence fr2serial {
P3-FS-1 high P3-FS-2 high P3-FS-3 high P3-FS-4 high P1-OR high
step(24)
P2-FS-1 low P2-FS-2 low P2-FS-3 low P2-FS-4 low
step(24)
P1-FS-1 high P1-FS-2 high P1-FS-3 high P1-FS-4 high
step(24)
P3-FS-1 low P3-FS-2 low P3-FS-3 low P3-FS-4 low
step(24)
P2-FS-1 high P2-FS-2 high P2-FS-3 high P2-FS-4 high
step(24)
P1-FS-1 low P1-FS-2 low P1-FS-3 low P1-FS-4 low P1-OR low
step(24)
}
Here, "fr2serial" is the name of the sequence block. "P3-FS-1" and similar are the names of CCD clocks and other digital signals. The convention here is to use the signal names from the schematics. "high" and "low" command the preceding signal to the high or low state. "step(24)" means delay 24 clock cycles before the next command (there are 15 clock cycles per µs, so 24 cycles is 1.6 µs). "step" without a count means "step(1)".
It is useful to have a common default state at the start of a sequence. A defaults block defines this:
defaults {
P1-IA-1 low P2-IA-1 high P3-IA-1 low
P1-IA-2 low P2-IA-2 high P3-IA-2 low
P1-IA-3 low P2-IA-3 high P3-IA-3 low
P1-IA-4 low P2-IA-4 high P3-IA-4 low
P1-FS-1 low P2-FS-1 high P3-FS-1 low
P1-FS-2 low P2-FS-2 high P3-FS-2 low
P1-FS-3 low P2-FS-3 high P3-FS-3 low
P1-FS-4 low P2-FS-4 high P3-FS-4 low
P1-OR low P2-OR high P3-OR low
P1-U low P2-U low P3-U low
RG high ID high
Int low DeInt low Clamp low CNV low
}
This defines the state at the beginning of each sequence block. It is a useful convention to have each block restore this state at its end to avoid surprising state changes, but this is not required. This example lists all of the 36 signals the sequencer controls.
The sequences are stored as bitmaps in a 1024 by 36 bit memory. This means that the total number of step() delays in the sequence blocks must be <=1024.
To execute a sequence block, use a statement like:
pixel_data ( 550 ) pixcycle;
This executes a block named "pixcycle" 550 times. The tag "pixel_data" indicates that the FPE FPGA should transmit the resulting video ADC output data to the DHU. If the tag had been "no_data", it would indicate that the FPGA should not transmit data.
Sequence execution commands may be enclosed in "do" blocks:
do (buffer_rows) {
no_data ( 1 ) fr2serial;
no_data ( physical_columns + overclock ) pixcycle
}
This executes the enclosed statements the number of times given by the "buffer_rows" parameter.
The DHU data link design incorporates the concept that part of the sequencer program produces a "frame". You designate that by wrapping the code that does this in a frame block:
frame {
do( rows ) {
no_data ( 1 ) fr2serial;
pixel_data ( physical_columns + overclock ) pixcycle;
}
}
Finally, the last statement in a sequencer program should be a "hold" statement:
hold pixcycle;
This will execute the "pixcycle" sequence indefinitely until the DHU commands a fresh frame start.