110 lines
3.3 KiB
C++
110 lines
3.3 KiB
C++
// STRIX raw capture tool: boots the STRIX FPGA image and gives the host (tools/jitter.py)
|
|
// register access and raw captures over USB serial. For characterization only; the device
|
|
// firmware is arduino/strix.
|
|
//
|
|
// Commands (one per line, numbers in decimal):
|
|
// id print the FPGA identification
|
|
// r <register> read a register, prints its value
|
|
// w <register> <value> write a register, prints "OK"
|
|
// cap start a capture with the current settings and send it as
|
|
// "DATA <n>\n" followed by n raw bytes
|
|
// stats print the latest statistics trial snapshot as hex
|
|
// amp print the latest bias amplifier trial snapshot as hex
|
|
|
|
#include <StrixFPGA.h>
|
|
|
|
using namespace strix;
|
|
|
|
const size_t CHUNK_BYTES = 512;
|
|
|
|
StrixFPGA fpga;
|
|
|
|
void printId() {
|
|
char id[5] = {0};
|
|
for (uint8_t i = 0; i < 4; i++) id[i] = fpga.read(REG_ID0 + i);
|
|
Serial.print(id);
|
|
Serial.print(" v");
|
|
Serial.println(fpga.read(REG_VERSION));
|
|
}
|
|
|
|
void capture() {
|
|
fpga.write(REG_CONTROL, CONTROL_START_CAPTURE);
|
|
|
|
// 262,144 samples at 120 MHz take up to 143 s at the maximum decimation of 65535.
|
|
unsigned long start = millis();
|
|
while (!(fpga.read(REG_STATUS) & STATUS_CAPTURE_DONE)) {
|
|
if (millis() - start > 180000) {
|
|
Serial.println("ERR timeout");
|
|
return;
|
|
}
|
|
}
|
|
|
|
Serial.print("DATA ");
|
|
Serial.println(CAPTURE_BYTES);
|
|
|
|
static uint8_t chunk[CHUNK_BYTES];
|
|
for (size_t sent = 0; sent < CAPTURE_BYTES; sent += CHUNK_BYTES) {
|
|
fpga.readBurst(REG_DATA, chunk, CHUNK_BYTES);
|
|
Serial.write(chunk, CHUNK_BYTES);
|
|
}
|
|
}
|
|
|
|
void printSnapshot(uint8_t reg, size_t length) {
|
|
uint8_t snapshot[STATS_SNAPSHOT_BYTES];
|
|
fpga.readBurst(reg, snapshot, length);
|
|
for (size_t i = 0; i < length; i++) {
|
|
if (snapshot[i] < 0x10) Serial.print('0');
|
|
Serial.print(snapshot[i], HEX);
|
|
}
|
|
Serial.println();
|
|
}
|
|
|
|
// Parses "<a>" or "<a> <b>" after the command word; returns the number of values found.
|
|
int parseArgs(const String &args, long &a, long &b) {
|
|
int space = args.indexOf(' ');
|
|
if (args.length() == 0) return 0;
|
|
a = args.substring(0, space < 0 ? args.length() : space).toInt();
|
|
if (space < 0) return 1;
|
|
b = args.substring(space + 1).toInt();
|
|
return 2;
|
|
}
|
|
|
|
void handleCommand(String line) {
|
|
line.trim();
|
|
int space = line.indexOf(' ');
|
|
String command = space < 0 ? line : line.substring(0, space);
|
|
String args = space < 0 ? "" : line.substring(space + 1);
|
|
long reg = 0, value = 0;
|
|
int count = parseArgs(args, reg, value);
|
|
|
|
if (command == "id") {
|
|
printId();
|
|
} else if (command == "r" && count == 1 && reg >= 0 && reg < 0x80) {
|
|
Serial.println(fpga.read(reg));
|
|
} else if (command == "w" && count == 2 && reg >= 0 && reg < 0x80 && value >= 0 && value < 256) {
|
|
fpga.write(reg, value);
|
|
Serial.println("OK");
|
|
} else if (command == "cap") {
|
|
capture();
|
|
} else if (command == "stats") {
|
|
printSnapshot(REG_STATS, STATS_SNAPSHOT_BYTES);
|
|
} else if (command == "amp") {
|
|
printSnapshot(REG_AMP, AMP_SNAPSHOT_BYTES);
|
|
} else if (line.length() > 0) {
|
|
Serial.println("ERR unknown or malformed command");
|
|
}
|
|
}
|
|
|
|
void setup() {
|
|
Serial.begin(115200);
|
|
while (!Serial);
|
|
|
|
if (!fpga.begin()) {
|
|
Serial.println("ERR FPGA boot failed");
|
|
}
|
|
printId();
|
|
}
|
|
|
|
void loop() {
|
|
if (Serial.available()) handleCommand(Serial.readStringUntil('\n'));
|
|
}
|