merged fdaq code

This commit is contained in:
2016-03-16 15:09:26 +01:00
parent e412ae7092
commit b014dd6afd
14 changed files with 870 additions and 3 deletions

View File

@@ -35,7 +35,7 @@ usage: viewer
# Development
When checking out the project from the repository there is the `target/generated-sources/xjc` folder missing.
After checking out the project execute `mvn compile` to create the folder and the required classes.
After checking out the project execute `mvn compile` to create the folder and the required classes.
To build project use `mvn clean install`.
@@ -114,3 +114,52 @@ ch.psi.fda.aq.crlogic.ioc=X05LA-VME-ES2
ch.psi.fda.aq.crlogic.prefix=X05LA-ES2-CRL
```
# FDAQ
## Overview
This software is used to readout the FDAQ box developed at X10SA.
On The FDAQ box there are 2 socket servers, one for retrieving the data and one for resetting the socket
server for data retrieval.
The fdaq code provides exactly 2 functionalities. It can query on the data socket for data (need to specifying how many data point to read),
and it can send a reset request on the reset channel.
## Usage
To acquire data into a file use:
```
java -jar ch.psi.fda.fdaq-<version>.jar <file>
```
You can terminate the acquisition with *CTRL+C*. If you submit 2 consequtive *CTRL+C* the program will terminate immediately (and data might be lost);
This will take the default connections settings:
* Hostname: mchip015.psi.ch
* Port: 2233
* Kill Port: 2234
* Number Of Elements: Integer.MAX_VALUE/2
If you need to specify different settings create a property files with following content:
```
ch.psi.fda.fdaq.hostname=myhost
ch.psi.fda.fdaq.port=1234
ch.psi.fda.fdaq.killPort=4321
```
Use `-Dch.psi.fda.fdaq.config.file=<file>` to use this property file as base configuration.
## Development
A standalone jar can be build via `mvn clean compile assembly:single`.
To upload the latest version to the artifact repository use ` mvn clean compile deploy`.
## Notes
Trigger port is `Trigger In 1`. For testing apply a 1kHz signal.

View File

@@ -14,7 +14,6 @@ repositories {
dependencies {
compile 'ch.psi:ch.psi.fda.core:2.3.4'
compile 'ch.psi.fda:ch.psi.fda.xscan:2.6.8'
compile 'ch.psi:ch.psi.fda.fdaq:2.3.4'
compile 'ch.psi:jcae:2.4.1'
compile 'com.google.inject:guice:3.0'
compile 'org.glassfish.jersey.containers:jersey-container-grizzly2-http:2.5.1'

View File

@@ -0,0 +1,198 @@
/**
*
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This code is distributed in the hope that it will be useful, but without any
* warranty; without even the implied warranty of merchantability or fitness for
* a particular purpose. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.fdaq;
import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import com.google.common.eventbus.EventBus;
import ch.psi.fda.messages.DataMessage;
import ch.psi.fda.messages.EndOfStreamMessage;
import ch.psi.fda.messages.Metadata;
public class Fdaq {
private static final Logger logger = Logger.getLogger(Fdaq.class.getName());
private volatile boolean stopAcquisition = false;
private volatile boolean running = false;
private final EventBus bus;
private FdaqConfiguration configuration;
private final int numberOfElements = Integer.MAX_VALUE/2;
public Fdaq(EventBus bus, FdaqConfiguration configuration){
this.bus = bus;
this.configuration = configuration;
}
/**
* Acquire data from the fdaq box
* @param hostname
* @param port
* @param numberOfElements
*/
public void acquire() {
running = true; // potential threading problem
final List<Metadata> metadata = new ArrayList<>();
metadata.add(new Metadata("counter"));
metadata.add(new Metadata("ain1"));
metadata.add(new Metadata("ain2"));
metadata.add(new Metadata("ain3"));
metadata.add(new Metadata("ain4"));
metadata.add(new Metadata("enc1"));
Socket echoSocket = null;
DataOutputStream out = null;
DataInputStream in = null;
boolean first = true;
while(running){
try {
stopAcquisition = false;
echoSocket = new Socket(configuration.getHostname(), configuration.getPort());
out = new DataOutputStream(echoSocket.getOutputStream());
in = new DataInputStream(new BufferedInputStream(echoSocket.getInputStream()));
ByteBuffer bytebuffer = ByteBuffer.allocate(3 * 4); // 3 times Integer
bytebuffer.order(ByteOrder.LITTLE_ENDIAN);
bytebuffer.putInt(26); // Function number (index of pointer to function)
bytebuffer.putInt(numberOfElements);
if(first){
bytebuffer.putInt(1); // Reset FIFO flag - The first time there need to be a 1 in int to reset the fifo buffer on the box
first=false;
}
else{
bytebuffer.putInt(0);
}
out.write(bytebuffer.array());
out.flush();
for (int t = 0; t < numberOfElements; t++) {
byte[] cbuffer = new byte[4*4]; // 4 times Integers a 4 bytes
try{
in.readFully(cbuffer);
}
catch(EOFException e){
logger.info("End of Stream");
break;
}
if(t<1028){
// The first 1028 are wrong (not really wrong but there are repeated values/holes)
// It has to do with the fact that we asynchronously reset the FIFO.
// This is independent of the frequency
continue;
}
ByteBuffer buffer = ByteBuffer.wrap(cbuffer);
buffer.order(ByteOrder.LITTLE_ENDIAN);
int a = buffer.getInt();
int b = buffer.getInt();
int b1 = b & 0xffff;
int b2 = (b >> 16) & 0xffff;
int c = buffer.getInt();
int c1 = c & 0xffff;
int c2 = (c >> 16) & 0xffff;
int d = buffer.getInt();
DataMessage message = new DataMessage(metadata);
message.getData().add(a);
message.getData().add(b1);
message.getData().add(b2);
message.getData().add(c1);
message.getData().add(c2);
message.getData().add(d);
bus.post(message);
}
logger.info("Done ...");
} catch (IOException e) {
// Ignore potential exceptions if stop was triggered before all messages were retrieved
if (!stopAcquisition) {
throw new RuntimeException(e);
}
} finally {
try {
if (out!=null)
out.close();
if (in!=null)
in.close();
if (echoSocket!=null)
echoSocket.close();
} catch (IOException e) {
// Ignore because not relevant at this stage
}
running = false;
}
}
bus.post(new EndOfStreamMessage());
}
/**
* Sending termination command to fdaq box
*/
public void stop() {
try {
running=false;
stopAcquisition = true;
Socket echoSocket = new Socket(configuration.getHostname(), configuration.getKillPort());
DataOutputStream out = new DataOutputStream(echoSocket.getOutputStream());
ByteBuffer bytebuffer = ByteBuffer.allocate(1 * 4); // 2
// times
// Integers
bytebuffer.order(ByteOrder.LITTLE_ENDIAN);
bytebuffer.putInt(666);
out.write(bytebuffer.array());
out.flush();
out.close();
echoSocket.close();
} catch (IOException e) {
logger.log(Level.SEVERE, "", e);
}
}
public boolean isRunning() {
return running;
}
}

View File

@@ -0,0 +1,78 @@
/**
*
* Copyright 2014 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This code is distributed in the hope that it will be useful, but without any
* warranty; without even the implied warranty of merchantability or fitness for
* a particular purpose. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.fdaq;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;
import java.util.logging.Logger;
public class FdaqConfiguration {
private static final Logger logger = Logger.getLogger(FdaqConfiguration.class.getName());
private final static String FDAQ_CONFIG = "ch.psi.fda.fdaq.config.file";
private String hostname = "mchip015.psi.ch";
private int port = 2233;
private int killPort = 2234;
public FdaqConfiguration(){
String config = System.getProperty(FDAQ_CONFIG);
if(config != null){
loadFile(new File(config));
}
else{
logger.warning("No configuration file specified via -D"+FDAQ_CONFIG+"=... - using defaults");
}
}
public void loadFile(File file) {
Properties properties = new Properties();
try {
properties.load(new FileReader(file));
} catch (IOException e) {
throw new RuntimeException("Cannot read file "+file, e);
}
hostname = properties.getProperty(FdaqConfiguration.class.getPackage().getName()+".hostname", hostname);
port = Integer.parseInt(properties.getProperty(FdaqConfiguration.class.getPackage().getName()+".port", port+""));
killPort = Integer.parseInt(properties.getProperty(FdaqConfiguration.class.getPackage().getName()+".killPort", killPort+""));
}
public String getHostname() {
return hostname;
}
public void setHostname(String hostname) {
this.hostname = hostname;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public int getKillPort() {
return killPort;
}
public void setKillPort(int killPort) {
this.killPort = killPort;
}
}

View File

@@ -0,0 +1,80 @@
/**
*
* Copyright 2014 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This code is distributed in the hope that it will be useful, but without any
* warranty; without even the implied warranty of merchantability or fitness for
* a particular purpose. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.fdaq;
import java.io.File;
import javax.inject.Inject;
import ch.psi.fda.EContainer;
import ch.psi.fda.fdaq.FdaqConfiguration;
import ch.psi.fda.serializer.SerializerTXT;
import com.google.common.eventbus.EventBus;
public class FdaqEContainer implements EContainer {
private Fdaq fdaq;
private EventBus bus;
private FdaqEDescriptor edescriptor;
@Inject
public FdaqEContainer(FdaqEDescriptor edescriptor, EventBus ebus){
this.bus = ebus;
this.edescriptor = edescriptor;
}
@Override
public void initialize() {
}
@Override
public void execute() {
if(fdaq!=null && fdaq.isRunning()){
throw new IllegalStateException("FDAQ is already running");
}
fdaq = new Fdaq(bus, new FdaqConfiguration());
File file = new File(edescriptor.getFileName());
file.getParentFile().mkdirs(); // Create data base directory
SerializerTXT serializer = new SerializerTXT(file);
serializer.setShowDimensionHeader(false);
bus.register(serializer);
fdaq.acquire();
}
@Override
public void abort() {
fdaq.stop();
}
@Override
public boolean isActive() {
return fdaq.isRunning();
}
@Override
public void destroy() {
}
}

View File

@@ -0,0 +1,20 @@
package ch.psi.fda.fdaq;
import com.google.common.eventbus.EventBus;
import ch.psi.fda.EContainer;
import ch.psi.fda.EContainerFactory;
import ch.psi.fda.edescriptor.EDescriptor;
public class FdaqEContainerFactory implements EContainerFactory {
@Override
public boolean supportsEDescriptor(EDescriptor descriptor) {
return descriptor instanceof FdaqEDescriptor;
}
@Override
public EContainer getEContainer(EDescriptor descriptor, EventBus bus) {
return new FdaqEContainer((FdaqEDescriptor) descriptor, bus);
}
}

View File

@@ -0,0 +1,18 @@
package ch.psi.fda.fdaq;
import javax.xml.bind.annotation.XmlRootElement;
import ch.psi.fda.edescriptor.EDescriptor;
@XmlRootElement(name="fdaq")
public class FdaqEDescriptor implements EDescriptor {
private String fileName;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
}

View File

@@ -0,0 +1,44 @@
package ch.psi.fda.fdaq;
import java.io.File;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import ch.psi.fda.DescriptorProvider;
import ch.psi.fda.edescriptor.EDescriptor;
import ch.psi.fda.vdescriptor.VDescriptor;
public class FdaqEDescriptorProvider implements DescriptorProvider {
private EDescriptor edescriptor;
@Override
public void load(File... files) {
try {
JAXBContext context = JAXBContext.newInstance(FdaqEDescriptor.class);
Unmarshaller u = context.createUnmarshaller();
edescriptor = (EDescriptor) u.unmarshal(files[0]);
} catch (JAXBException e) {
throw new RuntimeException(e);
}
}
@Override
public EDescriptor getEDescriptor() {
return edescriptor;
}
@Override
public VDescriptor getVDescriptor() {
return null;
}
@Override
public Class<?> getEDescriptorClass() {
return FdaqEDescriptor.class;
}
}

View File

@@ -0,0 +1,83 @@
/**
*
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This code is distributed in the hope that it will be useful, but without any
* warranty; without even the implied warranty of merchantability or fitness for
* a particular purpose. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.fdaq.ui;
import java.io.File;
import java.util.concurrent.Executors;
import sun.misc.Signal;
import sun.misc.SignalHandler;
import ch.psi.fda.fdaq.Fdaq;
import ch.psi.fda.fdaq.FdaqConfiguration;
import ch.psi.fda.serializer.SerializerTXT;
import com.google.common.eventbus.AsyncEventBus;
import com.google.common.eventbus.EventBus;
@SuppressWarnings("restriction")
public class FdaqMain {
public static void main(String[] args) {
if(args.length != 1){
System.err.println("Usage:\n fdaq <file>");
System.exit(-1);
}
File file = new File(args[0]);
if(file.exists()){
System.err.println("File "+file.getName()+ " already exists.");
System.exit(-1);
}
FdaqConfiguration configuration = new FdaqConfiguration();
EventBus bus = new AsyncEventBus(Executors.newSingleThreadExecutor());
final Fdaq fdaq = new Fdaq(bus, configuration);
Signal.handle(new Signal("INT"), new SignalHandler() {
int count = 0;
public void handle(Signal sig) {
if(count < 1){
fdaq.stop();
count++;
return;
}
System.exit(0);
}
});
SerializerTXT serializer = new SerializerTXT(file, false);
serializer.setShowDimensionHeader(false);
bus.register(serializer);
// This stop ensures that the data server is in a good shape (i.e. gets restarted)
// We need to wait a certain amount of time to have the server restarted.
fdaq.stop();
try {
Thread.sleep(1000); // TODO check whether this sleep is really necessary
} catch (InterruptedException e) {
e.printStackTrace();
}
fdaq.acquire();
}
}

View File

@@ -1 +1,2 @@
ch.psi.fda.cdump.CdumpEDescriptorProvider
ch.psi.fda.fdaq.FdaqEDescriptorProvider

View File

@@ -1 +1,2 @@
ch.psi.fda.cdump.CdumpEContainerFactory
ch.psi.fda.cdump.CdumpEContainerFactory
ch.psi.fda.fdaq.FdaqEContainerFactory

View File

@@ -0,0 +1,154 @@
/**
*
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This code is distributed in the hope that it will be useful, but without any
* warranty; without even the implied warranty of merchantability or fitness for
* a particular purpose. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.fdaq;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.util.logging.Logger;
/**
* Simple socket server emulating the fdaq black box.
*/
public class FdaqServer {
private static final Logger logger = Logger.getLogger(FdaqServer.class.getName());
private volatile boolean stop = false;
public void startKillSocket(int port) {
try {
ServerSocket serverSocket = new ServerSocket(port);
try{
while(true){
Socket socket = serverSocket.accept();
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream());
byte[] requestBuffer = new byte[1 * 4]; // 2 times integers
ByteBuffer bytebuffer = ByteBuffer.wrap(requestBuffer);
bytebuffer.order(ByteOrder.LITTLE_ENDIAN);
in.read(requestBuffer);
bytebuffer.getInt();
logger.info("Terminate sender");
stop=true;
out.close();
in.close();
socket.close();
}
}
finally{
serverSocket.close();
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void startSenderSocket(int port) {
stop = false;
try {
ServerSocket serverSocket = new ServerSocket(port);
try{
while(true){
Socket socket = serverSocket.accept();
stop = false;
logger.info("Start sending ...");
DataOutputStream out = new DataOutputStream(socket.getOutputStream());
DataInputStream in = new DataInputStream(socket.getInputStream());
byte[] requestBuffer = new byte[2 * 4]; // 2 times integers
ByteBuffer bytebuffer = ByteBuffer.wrap(requestBuffer);
bytebuffer.order(ByteOrder.LITTLE_ENDIAN);
in.read(requestBuffer);
bytebuffer.getInt(); // This will always be 26
int nMessages = bytebuffer.getInt(); // Contains number of images to
// receive
// System.out.println("Messages to send: "+nMessages);
for (int t = 0; t < nMessages; t++) {
if(stop){ // Terminate loop if kill socket got a request
break;
}
// System.out.println(t+" "+0+" "+0+" "+ (-t));
byte[] dataBuffer = new byte[4 * 4]; // 4 times Integers
ByteBuffer buffer = ByteBuffer.wrap(dataBuffer); // 4 times
// Integers
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putInt(t);
buffer.putInt(0);
buffer.putInt(0);
buffer.putInt(-t);
out.write(dataBuffer);
out.flush();
if(t>1028){ // The first 1028 images are skipped anyways
Thread.sleep(10);
}
}
out.close();
in.close();
socket.close();
}
}
finally{
serverSocket.close();
}
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
public static void main(String[] args) throws IOException, InterruptedException {
final FdaqConfiguration configuration = new FdaqConfiguration();
final FdaqServer server = new FdaqServer();
new Thread(new Runnable() {
@Override
public void run() {
server.startSenderSocket(configuration.getPort());
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
server.startKillSocket(configuration.getKillPort());
}
}).start();
}
}

View File

@@ -0,0 +1,87 @@
/**
*
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This code is distributed in the hope that it will be useful, but without any
* warranty; without even the implied warranty of merchantability or fitness for
* a particular purpose. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.fdaq;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Simple socket client to connect to the fdaq black box.
*/
public class SocketClient {
/**
* Requires connection to:
* ssh -L9999:mchip015:2233 x10da-gw
*
* @param args
* @throws IOException
* @throws InterruptedException
*/
public static void main(String[] args) throws IOException, InterruptedException {
// Socket echoSocket = new Socket("localhost", 9999);
// Socket echoSocket = new Socket("mchip015", 2233);
Socket echoSocket = new Socket("localhost", 2233);
DataOutputStream out = new DataOutputStream(echoSocket.getOutputStream());
DataInputStream in = new DataInputStream(echoSocket.getInputStream());
// int nMessages = 100;
int nMessages = Integer.MAX_VALUE;
// struct fdaqbloc_in {int fnum;int nsample;};
ByteBuffer bytebuffer = ByteBuffer.allocate(2*4); // 2 times Integers
bytebuffer.order(ByteOrder.LITTLE_ENDIAN);
bytebuffer.putInt(26);
bytebuffer.putInt(nMessages);
out.write(bytebuffer.array());
out.flush();
for (int t=0;t<nMessages;t++) {
// struct fdaqbloc_out {int trigindex;int adc1reg;int adc2reg;int encoder;};
ByteBuffer buffer = ByteBuffer.allocate(4*4); // 4 times Integers
buffer.order(ByteOrder.LITTLE_ENDIAN);
int r = in.read(buffer.array());
if(r == -1){
break;
}
int a = buffer.getInt();
int b = buffer.getInt();
int b1 = b&0xffff;
int b2 = (b>>16)&0xffff;
int c = buffer.getInt();
int c1 = c&0xffff;
int c2 = (c>>16)&0xffff;
int d = buffer.getInt();
System.out.println( a+ " " +b1+ " " +b2+ " " + c1+ " " +c2+ " " +d );
}
out.close();
in.close();
echoSocket.close();
}
}

View File

@@ -0,0 +1,55 @@
/**
*
* Copyright 2013 Paul Scherrer Institute. All rights reserved.
*
* This code is free software: you can redistribute it and/or modify it under
* the terms of the GNU Lesser General Public License as published by the Free
* Software Foundation, either version 3 of the License, or (at your option) any
* later version.
*
* This code is distributed in the hope that it will be useful, but without any
* warranty; without even the implied warranty of merchantability or fitness for
* a particular purpose. See the GNU Lesser General Public License for more
* details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this code. If not, see <http://www.gnu.org/licenses/>.
*
*/
package ch.psi.fda.fdaq;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Simple socket client to connect to the fdaq black box.
*/
public class SocketClientStop {
/**
* Requires connection to:
* ssh -L9998:mchip015:2234 x10da-gw
*
* @param args
* @throws IOException
* @throws InterruptedException
*/
public static void main(String[] args) throws IOException, InterruptedException {
// Socket echoSocket = new Socket("localhost", 9998);
Socket echoSocket = new Socket("localhost", 2234);
DataOutputStream out = new DataOutputStream(echoSocket.getOutputStream());
ByteBuffer bytebuffer = ByteBuffer.allocate(1*4); // 2 times Integers
bytebuffer.order(ByteOrder.LITTLE_ENDIAN);
bytebuffer.putInt(666);
out.write(bytebuffer.array());
out.flush();
out.close();
echoSocket.close();
}
}