Subversion Repositories f9daq

Compare Revisions

Ignore whitespace Rev 232 → Rev 238

/cvi/instr/RedPitaya/sockserv/fpga_osc.h
File deleted
/cvi/instr/RedPitaya/sockserv/daq.h
File deleted
/cvi/instr/RedPitaya/sockserv/version.h
File deleted
Property changes:
Deleted: svn:executable
Index: sockserv/calib.c
===================================================================
--- sockserv/calib.c (revision 232)
+++ sockserv/calib.c (nonexistent)
@@ -1,105 +0,0 @@
-/**
- * $Id: calib.c 881 2013-12-16 05:37:34Z rp_jmenart $
- *
- * @brief Red Pitaya Oscilloscope Calibration Module.
- *
- * @Author Jure Menart <juremenart@gmail.com>
- *
- * (c) Red Pitaya http://www.redpitaya.com
- *
- * This part of code is written in C programming language.
- * Please visit http://en.wikipedia.org/wiki/C_(programming_language)
- * for more details on the language used herein.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-
-#include "calib.h"
-
-const char eeprom_device[]="/sys/bus/i2c/devices/0-0050/eeprom";
-const int eeprom_calib_off=0x0008;
-
-
-/*----------------------------------------------------------------------------*/
-/**
- * @brief Read calibration parameters from EEPROM device.
- *
- * Function reads calibration parameters from EEPROM device and stores them to the
- * specified buffer. Communication to the EEPROM device is taken place through
- * appropriate system driver accessed through the file system device
- * /sys/bus/i2c/devices/0-0050/eeprom.
- *
- * @param[out] calib_params Pointer to destination buffer.
- * @retval 0 Success
- * @retval -1 Failure, error message is put on stderr device
- *
- */
-int rp_read_calib_params(rp_calib_params_t *calib_params)
-{
- FILE *fp;
- size_t size;
-
- /* sanity check */
- if(calib_params == NULL) {
- fprintf(stderr, "rp_read_calib_params(): input structure "
- "not initialized\n");
- return -1;
- }
-
- /* open eeprom device */
- fp=fopen(eeprom_device, "r");
- if(fp == NULL) {
- fprintf(stderr, "rp_read_calib_params(): Can not open EEPROM device: "
- " %s\n", strerror(errno));
- return -1;
- }
-
- /* ...and seek to the appropriate storage offset */
- if(fseek(fp, eeprom_calib_off, SEEK_SET) < 0) {
- fclose(fp);
- fprintf(stderr, "rp_read_calib_params(): fseek() failed: %s\n",
- strerror(errno));
- return -1;
- }
-
- /* read data from eeprom component and store it to the specified buffer */
- size=fread(calib_params, sizeof(char), sizeof(rp_calib_params_t), fp);
- if(size != sizeof(rp_calib_params_t)) {
- fclose(fp);
- fprintf(stderr, "rp_read_calib_params(): fread() failed, "
- "returned bytes: %d (should be :%d)\n", size,
- sizeof(rp_calib_params_t));
- return -1;
- }
- fclose(fp);
-
- return 0;
-}
-
-
-/*----------------------------------------------------------------------------*/
-/**
- * Initialize calibration parameters to default values.
- *
- * @param[out] calib_params Pointer to target buffer to be initialized.
- * @retval 0 Success, could never fail.
- */
-
-int rp_default_calib_params(rp_calib_params_t *calib_params)
-{
- calib_params->fe_ch1_fs_g_hi = 28101971; /* 0.6543 [V] */
- calib_params->fe_ch2_fs_g_hi = 28101971; /* 0.6543 [V] */
- calib_params->fe_ch1_fs_g_lo = 625682246; /* 14.56 [V] */
- calib_params->fe_ch2_fs_g_lo = 625682246; /* 14.56 [V] */
- calib_params->fe_ch1_dc_offs = 585;
- calib_params->fe_ch2_dc_offs = 585;
- calib_params->be_ch1_fs = 42949673; /* 1 [V] */
- calib_params->be_ch2_fs = 42949673; /* 1 [V] */
- calib_params->be_ch1_dc_offs = 0x3eac;
- calib_params->be_ch2_dc_offs = 0x3eac;
-
- return 0;
-}
Index: sockserv/Makefile
===================================================================
--- sockserv/Makefile (revision 232)
+++ sockserv/Makefile (nonexistent)
@@ -1,96 +0,0 @@
-CFLAGS = -DMRP
-#
-# $Id: Makefile 1249 2014-02-22 20:21:40Z ales.bardorfer $
-#
-# (c) Red Pitaya http://www.redpitaya.com
-#
-# Trigger
-# Trigger project source file.
-#
-# make CROSS_COMPILE=arm-linux-gnueabi- clean all
-# on PC and move to Red Pitaya:
-# scp trig root@172.16.255.27:/tmp
-#
-# This project file is written for GNU/Make software. For more details please
-# visit: http://www.gnu.org/software/make/manual/make.html
-# GNU Compiler Collection (GCC) tools are used for the compilation and linkage.
-# For the details about the usage and building please visit:
-# http://gcc.gnu.org/onlinedocs/gcc/
-#
-
-# Versioning system
-VERSION ?= 0.00-0000
-REVISION ?= devbuild
-
-# List of compiled object files (not yet linked to executable)
-OBJS = sockserv.o fpga_osc.o calib.o daq.o
-# List of raw source files (all object files, renamed from .o to .c)
-SRCS = $(subst .o,.c, $(OBJS)))
-
-# Executable name
-TARGET=sockserv
-
-# GCC compiling & linking flags
-CFLAGS += -g -std=gnu99 -Wall -Werror
-CFLAGS += -DVERSION=$(VERSION) -DREVISION=$(REVISION)
-CFLAGS += -DDEBUG
-CFLAGS += -I/opt/redpitaya/include
-CFLAGS += -L/opt/redpitaya/lib
-#LDLIBS = -lm -lpthread -lrp
-# Red Pitaya common SW directory
-SHARED=/opt/redpitaya
-
-# Additional libraries which needs to be dynamically linked to the executable
-# -lm - System math library (used by cos(), sin(), sqrt(), ... functions)
-LIBS=-lm -lpthread -lrp
-
-# Main GCC executable (used for compiling and linking)
-CC=$(CROSS_COMPILE)gcc
-# Installation directory
-INSTALL_DIR ?= .
-
-# Makefile is composed of so called 'targets'. They give basic structure what
-# needs to be execued during various stages of the building/removing/installing
-# of software package.
-# Simple Makefile targets have the following structure:
-# <name>: <dependencies>
-# <command1>
-# <command2>
-# ...
-# The target <name> is completed in the following order:
-# - list od <dependencies> finished
-# - all <commands> in the body of targets are executed succsesfully
-
-# Main Makefile target 'all' - it iterates over all targets listed in $(TARGET)
-# variable.
-all: $(TARGET)
-
-# Target with compilation rules to compile object from source files.
-# It applies to all files ending with .o. During partial building only new object
-# files are created for the source files (.c) which have newer timestamp then
-# objects (.o) files.
-%.o: %.c version.h
- $(CC) -c $(CFLAGS) $< -o $@
-
-# Makefile target with rules how to link executable for each target from $(TARGET)
-# list.
-$(TARGET): $(OBJS)
- $(CC) -o $@ $^ $(CFLAGS) $(LIBS)
-
-# Version header for traceability
-version.h:
- cp $(SHARED)/include/redpitaya/version.h .
-
-# Clean target - when called it cleans all object files and executables.
-clean:
- rm -f $(TARGET) *.o
-
-# Install target - creates 'bin/' sub-directory in $(INSTALL_DIR) and copies all
-# executables to that location.
-install:
- mkdir -p $(INSTALL_DIR)/bin
- cp $(TARGET) $(INSTALL_DIR)/bin
- mkdir -p $(INSTALL_DIR)/src/utils/$(TARGET)
- -rm -f $(TARGET) *.o
- cp -r * $(INSTALL_DIR)/src/utils/$(TARGET)/
- -rm `find $(INSTALL_DIR)/src/tools/$(TARGET)/ -iname .svn` -rf
Index: sockserv/daqprofile.sh
===================================================================
--- sockserv/daqprofile.sh (revision 232)
+++ sockserv/daqprofile.sh (nonexistent)
@@ -1 +0,0 @@
-export LD_LIBRARY_PATH=/opt/redpitaya/lib/
Index: sockserv/calib.h
===================================================================
--- sockserv/calib.h (revision 232)
+++ sockserv/calib.h (nonexistent)
@@ -1,45 +0,0 @@
-/**
- * $Id: calib.h 881 2013-12-16 05:37:34Z rp_jmenart $
- *
- * @brief Red Pitaya Oscilloscope Calibration Module.
- *
- * @Author Jure Menart <juremenart@gmail.com>
- *
- * (c) Red Pitaya http://www.redpitaya.com
- *
- * This part of code is written in C programming language.
- * Please visit http://en.wikipedia.org/wiki/C_(programming_language)
- * for more details on the language used herein.
- */
-
-#ifndef __CALIB_H
-#define __CALIB_H
-
-#include <stdint.h>
-
-/** @defgroup calib_h Calibration
- * @{
- */
-
-/** Calibration parameters, stored in eeprom device
- */
-typedef struct rp_osc_calib_params_s {
- uint32_t fe_ch1_fs_g_hi; /**< High gain front end full scale voltage, channel 1 */
- uint32_t fe_ch2_fs_g_hi; /**< High gain front end full scale voltage, channel 2 */
- uint32_t fe_ch1_fs_g_lo; /**< Low gain front end full scale voltage, channel 1 */
- uint32_t fe_ch2_fs_g_lo; /**< Low gain front end full scale voltage, channel 2 */
- int32_t fe_ch1_dc_offs; /**< Front end DC offset, channel 1 */
- int32_t fe_ch2_dc_offs; /**< Front end DC offset, channel 2 */
- uint32_t be_ch1_fs; /**< Back end full scale voltage, channel 1 */
- uint32_t be_ch2_fs; /**< Back end full scale voltage, channel 2 */
- int32_t be_ch1_dc_offs; /**< Back end DC offset, channel 1 */
- int32_t be_ch2_dc_offs; /**< Back end DC offset, on channel 2 */
-} rp_calib_params_t;
-
-/** @} */
-
-int rp_read_calib_params(rp_calib_params_t *calib_params);
-
-int rp_default_calib_params(rp_calib_params_t *calib_params);
-
-#endif //__CALIB_H
Index: sockserv/sockserv.c
===================================================================
--- sockserv/sockserv.c (revision 232)
+++ sockserv/sockserv.c (nonexistent)
@@ -1,209 +0,0 @@
-/*
- C socket server example, handles multiple clients using threads */
-
-#include<stdio.h>
-#include<string.h> //strlen
-#include<stdlib.h> //strlen
-#include<sys/socket.h>
-#include<arpa/inet.h> //inet_addr
-#include<unistd.h>
-#//write
-#include<pthread.h>
-#include "daq.h"
-#define PORT 9930
-//the thread function
-
-
-
-void *connection_handler(void *);
-
-int is_connected = 0;
-int ncalls=0;
-extern int ctrl_c;
-
-int writesock(int sock, int id , char *msg, int len ){
- int hdr[2];
- hdr[0]= id;
- hdr[1]= len + 8;
- write(sock , hdr , 8);
- return write(sock , msg , len);
-}
-
-
-int main(int argc , char *argv[]) {
- int socket_desc , client_sock , c , *new_sock=NULL;
- struct sockaddr_in server , client;
-
- if (argc >1) return daq_main(argc, argv);
-
- //Create socket
- socket_desc = socket(AF_INET , SOCK_STREAM , 0);
- if (socket_desc == -1)
- {
- printf("Could not create socket");
- }
- puts("Socket created");
-
- //Prepare the sockaddr_in structure
- server.sin_family = AF_INET;
- server.sin_addr.s_addr = INADDR_ANY;
- server.sin_port = htons( PORT );
-
- //Bind
- if( bind(socket_desc,(struct sockaddr *)&server , sizeof(server)) < 0)
- {
- //print the error message
- perror("bind failed. Error");
- return 1;
- }
- puts("bind done");
-
- //Listen
- listen(socket_desc , 3);
-
- //Accept and incoming connection
- puts("Waiting for incoming connections...");
- c = sizeof(struct sockaddr_in);
-
-
- //Accept and incoming connection
- puts("Waiting for incoming connections...");
- c = sizeof(struct sockaddr_in);
- while( (client_sock = accept(socket_desc, (struct sockaddr *)&client, (socklen_t*)&c)) )
- {
- puts("Connection accepted");
-
- pthread_t sniffer_thread;
-
- if (is_connected){
- char message[0xFF]="Only one client can connect. Disconnect it first!";
- perror(message);
- writesock(client_sock , 0, message , strlen(message));
- close (client_sock);
- continue;
- }
- new_sock = (int *) malloc(1);
- *new_sock = client_sock;
- if( pthread_create( &sniffer_thread , NULL , connection_handler , (void*) new_sock) < 0)
- {
- perror("could not create thread");
- return 1;
- }
-
-
- //Now join the thread , so that we dont terminate before the thread
- //pthread_join( sniffer_thread , NULL);
-
- puts("Handler assigned");
-
- }
-
- if (client_sock < 0)
- {
- perror("accept failed");
- return 1;
- }
-
- return 0;
-}
-
-
-
-void *daq_handler(void *rdata){
-
- pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
- //Get the socket descriptor
- int sock = *(int*)rdata;
- int *idata = (int *)rdata;
-
- char * settings = (char *) (idata+2);
- daq_init(settings);
- settings +=12;
- int bufsize = 0;
- char * data = NULL;
-
- //for(int i =0;i<5;i++) printf("%d %d\n",i, idata[i]);
- while (1){
- int nb = daq_run ( settings, &data, &bufsize );
- int error = 0;
- socklen_t len = sizeof (error);
- int retval = getsockopt (sock, SOL_SOCKET, SO_ERROR, &error, &len);
- if (retval!=0 || error!=0) break;
- writesock(sock , 1, data , nb );
- if (ctrl_c) break;
- //break;
- }
- if (data!=NULL) free(data);
- fprintf(stderr, "Exiting thread %d\n", sock ) ;
- return NULL;
-}
-
-/*
- * This will handle connection for each client
- * */
-
-void *connection_handler(void *socket_desc) {
- //Get the socket descriptor
- int sock = *(int*)socket_desc;
- int read_size;
- char *message , client_message[2000];
- is_connected = 1;
- //Send some messages to the client
- message = "Info from connection handler\n";
- writesock(sock , 0, message , strlen(message));
-
- //Receive a message from client
- pthread_t daq_thread = 0;
-
- while( (read_size = recv(sock , client_message , 2000 , 0)) > 0 )
- {
- //Send the message back to client
- int * hdr = (int *) client_message;
- printf("Received %d bytes RECID = %d LEN %d\n",read_size, hdr[0], hdr[1]);
- switch (hdr[0]){
- case 0:
- ctrl_c = 0;
- hdr[0]= sock;
- if( pthread_create( &daq_thread , NULL , daq_handler , (void*) &client_message) < 0)
- {
- perror("could not create daq thread");
- }
- break;
- case 1:
- ctrl_c = 1;
- sleep(1);
- if (daq_thread) {
- pthread_cancel(daq_thread);
- daq_thread = 0;
- }
-
- break;
- default: break;
-
- }
- }
-
- if(read_size == 0)
- {
- puts("Client disconnected");
- fflush(stdout);
- }
- else if(read_size == -1)
- {
- perror("recv failed");
-
- }
- if (daq_thread) {
- pthread_cancel(daq_thread);
- daq_thread = 0;
- }
-
-
- //Free the socket pointer
- free(socket_desc);
- socket_desc = 0;
- is_connected = 0;
-
- return 0;
-}
-
Index: sockserv/fpga_osc.c
===================================================================
--- sockserv/fpga_osc.c (revision 232)
+++ sockserv/fpga_osc.c (nonexistent)
@@ -1,564 +0,0 @@
-/**
- * $Id: fpga_osc.c 881 2013-12-16 05:37:34Z rp_jmenart $
- *
- * @brief Red Pitaya Oscilloscope FPGA controller.
- *
- * @Author Jure Menart <juremenart@gmail.com>
- *
- * (c) Red Pitaya http://www.redpitaya.com
- *
- * This part of code is written in C programming language.
- * Please visit http://en.wikipedia.org/wiki/C_(programming_language)
- * for more details on the language used herein.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <math.h>
-#include <errno.h>
-#include <sys/mman.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-#include "fpga_osc.h"
-
-/**
- * GENERAL DESCRIPTION:
- *
- * This module initializes and provides for other SW modules the access to the
- * FPGA OSC module. The oscilloscope memory space is divided to three parts:
- * - registers (control and status)
- * - input signal buffer (Channel A)
- * - input signal buffer (Channel B)
- *
- * This module maps physical address of the oscilloscope core to the logical
- * address, which can be used in the GNU/Linux user-space. To achieve this,
- * OSC_FPGA_BASE_ADDR from CPU memory space is translated automatically to
- * logical address with the function mmap(). After all the initialization is done,
- * other modules can use this module to controll oscilloscope FPGA core. Before
- * any functions or functionality from this module can be used it needs to be
- * initialized with osc_fpga_init() function. When this module is no longer
- * needed osc_fpga_exit() must be called.
- *
- * FPGA oscilloscope state machine in various modes. Basic principle is that
- * SW sets the machine, 'arm' the writting machine (FPGA writes from ADC to
- * input buffer memory) and then set the triggers. FPGA machine is continue
- * writting to the buffers until the trigger is detected plus the amount set
- * in trigger delay register. For more detauled description see the FPGA OSC
- * registers description.
- *
- * Nice example how to use this module can be seen in worker.c module.
- */
-
-/* internal structures */
-/** The FPGA register structure (defined in fpga_osc.h) */
-osc_fpga_reg_mem_t *g_osc_fpga_reg_mem = NULL;
-/** The FPGA input signal buffer pointer for channel A */
-uint32_t *g_osc_fpga_cha_mem = NULL;
-/** The FPGA input signal buffer pointer for channel B */
-uint32_t *g_osc_fpga_chb_mem = NULL;
-
-/** The memory file descriptor used to mmap() the FPGA space */
-int g_osc_fpga_mem_fd = -1;
-
-/* Constants */
-/** ADC number of bits */
-const int c_osc_fpga_adc_bits = 14;
-/** @brief Max and min voltage on ADCs.
- * Symetrical - Max Voltage = +14, Min voltage = -1 * c_osc_fpga_max_v
- */
-const float c_osc_fpga_adc_max_v = +14;
-/** Sampling frequency = 125Mspmpls (non-decimated) */
-const float c_osc_fpga_smpl_freq = 125e6;
-/** Sampling period (non-decimated) - 8 [ns] */
-const float c_osc_fpga_smpl_period = (1. / 125e6);
-
-/**
- * @brief Internal function used to clean up memory.
- *
- * This function un-maps FPGA register and signal buffers, closes memory file
- * descriptor and cleans all memory allocated by this module.
- *
- * @retval 0 Success
- * @retval -1 Error happened during cleanup.
- */
-int __osc_fpga_cleanup_mem(void)
-{
- /* If register structure is NULL we do not need to un-map and clean up */
- if(g_osc_fpga_reg_mem) {
- if(munmap(g_osc_fpga_reg_mem, OSC_FPGA_BASE_SIZE) < 0) {
- fprintf(stderr, "munmap() failed: %s\n", strerror(errno));
- return -1;
- }
- g_osc_fpga_reg_mem = NULL;
- if(g_osc_fpga_cha_mem)
- g_osc_fpga_cha_mem = NULL;
- if(g_osc_fpga_chb_mem)
- g_osc_fpga_chb_mem = NULL;
- }
- if(g_osc_fpga_mem_fd >= 0) {
- close(g_osc_fpga_mem_fd);
- g_osc_fpga_mem_fd = -1;
- }
- return 0;
-}
-
-/**
- * @brief Maps FPGA memory space and prepares register and buffer variables.
- *
- * This function opens memory device (/dev/mem) and maps physical memory address
- * OSC_FPGA_BASE_ADDR (of length OSC_FPGA_BASE_SIZE) to logical addresses. It
- * initializes the pointers g_osc_fpga_reg_mem, g_osc_fpga_cha_mem and
- * g_osc_fpga_chb_mem to point to FPGA OSC.
- * If function failes FPGA variables must not be used.
- *
- * @retval 0 Success
- * @retval -1 Failure, error is printed to standard error output.
- */
-int osc_fpga_init(void)
-{
- /* Page variables used to calculate correct mapping addresses */
- void *page_ptr;
- long page_addr, page_off, page_size = sysconf(_SC_PAGESIZE);
-
- /* If module was already initialized once, clean all internals. */
- if(__osc_fpga_cleanup_mem() < 0)
- return -1;
-
- /* Open /dev/mem to access directly system memory */
- g_osc_fpga_mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
- if(g_osc_fpga_mem_fd < 0) {
- fprintf(stderr, "open(/dev/mem) failed: %s\n", strerror(errno));
- return -1;
- }
-
- /* Calculate correct page address and offset from OSC_FPGA_BASE_ADDR and
- * OSC_FPGA_BASE_SIZE
- */
- page_addr = OSC_FPGA_BASE_ADDR & (~(page_size-1));
- page_off = OSC_FPGA_BASE_ADDR - page_addr;
-
- /* Map FPGA memory space to page_ptr. */
- page_ptr = mmap(NULL, OSC_FPGA_BASE_SIZE, PROT_READ | PROT_WRITE,
- MAP_SHARED, g_osc_fpga_mem_fd, page_addr);
- if((void *)page_ptr == MAP_FAILED) {
- fprintf(stderr, "mmap() failed: %s\n", strerror(errno));
- __osc_fpga_cleanup_mem();
- return -1;
- }
-
- /* Set FPGA OSC module pointers to correct values. */
- g_osc_fpga_reg_mem = page_ptr + page_off;
- g_osc_fpga_cha_mem = (uint32_t *)g_osc_fpga_reg_mem +
- (OSC_FPGA_CHA_OFFSET / sizeof(uint32_t));
- g_osc_fpga_chb_mem = (uint32_t *)g_osc_fpga_reg_mem +
- (OSC_FPGA_CHB_OFFSET / sizeof(uint32_t));
-
- return 0;
-}
-
-/**
- * @brief Cleans up FPGA OSC module internals.
- *
- * This function closes the memory file descriptor, unmap the FPGA memory space
- * and cleans also all other internal things from FPGA OSC module.
- * @retval 0 Sucess
- * @retval -1 Failure
- */
-int osc_fpga_exit(void)
-{
- return __osc_fpga_cleanup_mem();
-}
-
-// TODO: Move to a shared folder and share with scope & spectrum.
-/**
- * @brief Provides equalization & shaping filter coefficients.
- *
- *
- * This function provides equalization & shaping filter coefficients, based on
- * the type of use and gain settings.
- *
- * @param [in] equal Enable(1)/disable(0) equalization filter.
- * @param [in] shaping Enable(1)/disable(0) shaping filter.
- * @param [in] gain Gain setting (0 = LV, 1 = HV).
- * @param [out] filt Filter coefficients.
- */
-void get_equ_shape_filter(ecu_shape_filter_t *filt, uint32_t equal,
- uint32_t shaping, uint32_t gain)
-{
- /* Equalization filter */
- if (equal) {
- if (gain == 0) {
- /* High gain = LV */
- filt->aa = 0x7D93;
- filt->bb = 0x437C7;
- } else {
- /* Low gain = HV */
- filt->aa = 0x4C5F;
- filt->bb = 0x2F38B;
- }
- } else {
- filt->aa = 0;
- filt->bb = 0;
- }
-
- /* Shaping filter */
- if (shaping) {
- filt->pp = 0x2666;
- filt->kk = 0xd9999a;
- } else {
- filt->pp = 0;
- filt->kk = 0xffffff;
- }
-}
-
-
-/**
- * @brief Updates triggering parameters in FPGA registers.
- *
- * This function updates trigger related parameters in FPGA registers.
- *
- * @param [in] trig_imm Trigger immediately - if set to 1, FPGA state machine
- * will trigger immediately and other trigger parameters
- * will be ignored.
- * @param [in] trig_source Trigger source, as defined in rp_main_params.
- * @param [in] trig_edge Trigger edge, as defined in rp_main_params.
- * @param [in] trig_delay Trigger delay in [s].
- * @param [in] trig_level Trigger level in [V].
- * @param [in] time_range Time range, as defined in rp_main_params.
- * @param [in] equal Enable(1)/disable(0) equalization filter.
- * @param [in] shaping Enable(1)/disable(0) shaping filter.
- * @param [in] gain1 Gain setting for Channel1 (0 = LV, 1 = HV).
- * @param [in] gain2 Gain setting for Channel2 (0 = LV, 1 = HV).
- *
- *
- * @retval 0 Success
- * @retval -1 Failure
- *
- * @see rp_main_params
- */
-int osc_fpga_update_params(int trig_imm, int trig_source, int trig_edge,
- float trig_delay, float trig_level, int time_range,
- int equal, int shaping, int gain1, int gain2)
-{
- int fpga_trig_source = osc_fpga_cnv_trig_source(trig_imm, trig_source,
- trig_edge);
- int fpga_dec_factor = osc_fpga_cnv_time_range_to_dec(time_range);
- int fpga_delay;
- float after_trigger; /* how much after trigger FPGA should write */
- int fpga_trig_thr = osc_fpga_cnv_v_to_cnt(trig_level);
-
- /* Equalization filter coefficients */
- ecu_shape_filter_t cha_filt;
- ecu_shape_filter_t chb_filt;
- get_equ_shape_filter(&cha_filt, equal, shaping, gain1);
- get_equ_shape_filter(&chb_filt, equal, shaping, gain2);
-
- if((fpga_trig_source < 0) || (fpga_dec_factor < 0)) {
- fprintf(stderr, "osc_fpga_update_params() failed\n");
- return -1;
- }
-
- /* Pre-trigger - we need to limit after trigger acquisition so we can
- * readout historic (pre-trigger) values */
-
- if (trig_imm)
- after_trigger=OSC_FPGA_SIG_LEN* c_osc_fpga_smpl_period * fpga_dec_factor;
- else
- after_trigger =
- ((OSC_FPGA_SIG_LEN-7) * c_osc_fpga_smpl_period * fpga_dec_factor) +
- trig_delay;
-
- if(after_trigger < 0)
- after_trigger = 0;
-
- fpga_delay = osc_fpga_cnv_time_to_smpls(after_trigger, fpga_dec_factor);
-
- /* Trig source is written after ARM */
- /* g_osc_fpga_reg_mem->trig_source = fpga_trig_source;*/
- if(trig_source == 0)
- g_osc_fpga_reg_mem->cha_thr = fpga_trig_thr;
- else
- g_osc_fpga_reg_mem->chb_thr = fpga_trig_thr;
-
- g_osc_fpga_reg_mem->data_dec = fpga_dec_factor;
- g_osc_fpga_reg_mem->trigger_delay = (uint32_t)fpga_delay;
-
- /* Update equalization filter with desired coefficients. */
- g_osc_fpga_reg_mem->cha_filt_aa = cha_filt.aa;
- g_osc_fpga_reg_mem->cha_filt_bb = cha_filt.bb;
- g_osc_fpga_reg_mem->cha_filt_pp = cha_filt.pp;
- g_osc_fpga_reg_mem->cha_filt_kk = cha_filt.kk;
-
- g_osc_fpga_reg_mem->chb_filt_aa = chb_filt.aa;
- g_osc_fpga_reg_mem->chb_filt_bb = chb_filt.bb;
- g_osc_fpga_reg_mem->chb_filt_pp = chb_filt.pp;
- g_osc_fpga_reg_mem->chb_filt_kk = chb_filt.kk;
-
- return 0;
-}
-
-/** @brief OSC FPGA reset
- *
- * Triggers internal oscilloscope FPGA state machine reset.
- *
- * @retval 0 Always returns 0.
- */
-int osc_fpga_reset(void)
-{
- g_osc_fpga_reg_mem->conf |= OSC_FPGA_CONF_RST_BIT;
- return 0;
-}
-
-/** @brief OSC FPGA ARM
- *
- * ARM internal oscilloscope FPGA state machine to start writting input buffers.
-
- * @retval 0 Always returns 0.
- */
-int osc_fpga_arm_trigger(void)
-{
- g_osc_fpga_reg_mem->conf |= OSC_FPGA_CONF_ARM_BIT;
-
- return 0;
-}
-
-/** @brief Sets the trigger source in OSC FPGA register.
- *
- * Sets the trigger source in oscilloscope FPGA register.
- *
- * @param [in] trig_source Trigger source, as defined in FPGA register
- * description.
- */
-int osc_fpga_set_trigger(uint32_t trig_source)
-{
- g_osc_fpga_reg_mem->trig_source = trig_source;
- return 0;
-}
-
-/** @brief Sets the trigger delay in OSC FPGA register.
- *
- * Sets the trigger delay in oscilloscope FPGA register.
- *
- * @param [in] trig_delay Trigger delay, as defined in FPGA register
- * description.
- *
- * @retval 0 Always returns 0.
- */
-int osc_fpga_set_trigger_delay(uint32_t trig_delay)
-{
- g_osc_fpga_reg_mem->trigger_delay = trig_delay;
- return 0;
-}
-
-/** @brief Checks if FPGA detected trigger.
- *
- * This function checks if trigger was detected by the FPGA.
- *
- * @retval 0 Trigger not detected.
- * @retval 1 Trigger detected.
- */
-int osc_fpga_triggered(void)
-{
- return ((g_osc_fpga_reg_mem->trig_source & OSC_FPGA_TRIG_SRC_MASK)==0);
-}
-
-/** @brief Returns memory pointers for both input signal buffers.
- *
- * This function returns pointers for input signal buffers for both channels.
- *
- * @param [out] cha_signal Output pointer for Channel A buffer
- * @param [out] cha_signal Output pointer for Channel B buffer
- *
- * @retval 0 Always returns 0.
- */
-int osc_fpga_get_sig_ptr(int **cha_signal, int **chb_signal)
-{
- *cha_signal = (int *)g_osc_fpga_cha_mem;
- *chb_signal = (int *)g_osc_fpga_chb_mem;
- return 0;
-}
-
-/** @brief Returns values for current and trigger write FPGA pointers.
- *
- * This functions returns values for current and trigger write pointers. They
- * are an address of the input signal buffer and are the same for both channels.
- *
- * @param [out] wr_ptr_curr Current FPGA input buffer address.
- * @param [out] wr_ptr_trig Trigger FPGA input buffer address.
- *
- * @retval 0 Always returns 0.
- */
-int osc_fpga_get_wr_ptr(int *wr_ptr_curr, int *wr_ptr_trig)
-{
- if(wr_ptr_curr)
- *wr_ptr_curr = g_osc_fpga_reg_mem->wr_ptr_cur;
- if(wr_ptr_trig)
- *wr_ptr_trig = g_osc_fpga_reg_mem->wr_ptr_trigger;
- return 0;
-}
-
-/** @brief Convert trigger parameters to FPGA trigger source value.
- *
- * This function takes as an argument trigger parameters and converts it to
- * trigger source value used by the FPGA trigger source reigster.
- *
- * @param [in] trig_imm Trigger immediately, if set to 1 other trigger parameters
- * are ignored.
- * @param [in] trig_source Trigger source as defined in rp_main_params
- * @param [in] trig_edge Trigger edge as defined in rp_main_params
- *
- * @retval -1 Error
- * @retval otherwise Trigger source FPGA value
- */
-int osc_fpga_cnv_trig_source(int trig_imm, int trig_source, int trig_edge)
-{
- int fpga_trig_source = 0;
-
- /* Trigger immediately */
- if(trig_imm)
- return 1;
-
- switch(trig_source) {
- case 0: /* ChA*/
- if(trig_edge == 0)
- fpga_trig_source = 2;
- else
- fpga_trig_source = 3;
- break;
- case 1: /* ChB*/
- if(trig_edge == 0)
- fpga_trig_source = 4;
- else
- fpga_trig_source = 5;
- break;
- case 2: /* External */
- if(trig_edge == 0)
- fpga_trig_source = 6;
- else
- fpga_trig_source = 7;
-
- break;
- default:
- /* Error */
- return -1;
- }
-
- return fpga_trig_source;
-}
-
-/** @brief Converts time range to decimation value.
- *
- * This function converts time range value defined by rp_main_params to
- * decimation factor value.
- *
- * @param [in] time_range Time range, integer between 0 and 5, as defined by
- * rp_main_params.
- *
- * @retval -1 Error
- *
- * @retval otherwise Decimation factor.
-*/
-int osc_fpga_cnv_time_range_to_dec(int time_range)
-{
- /* Input: 0, 1, 2, 3, 4, 5 translates to:
- * Output: 1x, 8x, 64x, 1kx, 8kx, 65kx */
- switch(time_range) {
- case 0:
- return 1;
- break;
- case 1:
- return 8;
- break;
- case 2:
- return 64;
- break;
- case 3:
- return 1024;
- break;
- case 4:
- return 8*1024;
- break;
- case 5:
- return 64*1024;
- break;
- default:
- return -1;
- }
-
- return -1;
-}
-
-/** @brief Converts time to number of samples.
- *
- * This function converts time in [s], based on current decimation factor to
- * number of samples at ADC sampling frequency.
- *
- * @param [in] time Time in [s]
- * @param [in] dec_factor Decimation factor
- *
- * @retval Number of ADC samples define dby input parameters.
- */
-int osc_fpga_cnv_time_to_smpls(float time, int dec_factor)
-{
- /* Calculate sampling period (including decimation) */
- float smpl_p = (c_osc_fpga_smpl_period * dec_factor);
- int fpga_smpls = (int)round(time / smpl_p);
-
- return fpga_smpls;
-}
-
-/** @brief Converts voltage to ADC counts.
- *
- * This function converts voltage in [V] to ADC counts.
- *
- * @param [in] voltage Voltage in [V]
- *
- * @retval adc_cnts ADC counts
- */
-int osc_fpga_cnv_v_to_cnt(float voltage)
-{
- int adc_cnts = 0;
-
- if((voltage > c_osc_fpga_adc_max_v) || (voltage < -c_osc_fpga_adc_max_v))
- return -1;
-
- adc_cnts = (int)round(voltage * (float)((int)(1<<c_osc_fpga_adc_bits)) /
- (2*c_osc_fpga_adc_max_v));
-
- /* Clip highest value (+14 is calculated in int32_t to 0x2000, but we have
- * only 14 bits
- */
- if((voltage > 0) && (adc_cnts & (1<<(c_osc_fpga_adc_bits-1))))
- adc_cnts = (1<<(c_osc_fpga_adc_bits-1))-1;
- else
- adc_cnts = adc_cnts & ((1<<(c_osc_fpga_adc_bits))-1);
-
- return adc_cnts;
-}
-
-/** @brief Converts ADC counts to voltage
- *
- * This function converts ADC counts to voltage (in [V])
- *
- * @param [in] cnts ADC counts
- *
- * @retval voltage Voltage in [V]
- */
-float osc_fpga_cnv_cnt_to_v(int cnts)
-{
- int m;
-
- if(cnts & (1<<(c_osc_fpga_adc_bits-1))) {
- /* negative number */
- m = -1 *((cnts ^ ((1<<c_osc_fpga_adc_bits)-1)) + 1);
- } else {
- m = cnts;
- /* positive number */
- }
- return m;
-}
-
Index: sockserv/daq.c
===================================================================
--- sockserv/daq.c (revision 232)
+++ sockserv/daq.c (nonexistent)
@@ -1,445 +0,0 @@
-#include <stdlib.h>
-#include <stdio.h>
-#include <signal.h>
-#include <time.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/time.h>
-#include <ctype.h>
-#include <unistd.h>
-
-#ifdef MRP
-#include "redpitaya/rp.h"
-#else
-#include "calib.h"
-#endif
-
-#include "fpga_osc.h"
-
-#define TRUE -1
-#define FALSE 0
-
-int timer_out; struct sigaction oact;
-
-int ctrl_c=0;
-
-void SigInt (int sig) {
- ctrl_c = 1;
-}
-
-
-void timerast (signumber, code, context) int signumber, code; struct sigcontext context; {
- fprintf(stderr, "Timeout\n");
- timer_out = TRUE;
-}
-
-void tmlnk (tout) int tout; {
- struct sigaction act;
- struct itimerval tdelay;
-
- act.sa_handler = timerast;
- sigemptyset (&act.sa_mask);
- act.sa_flags = 0;
-
- tdelay.it_value.tv_sec = tout / 100;
- tdelay.it_value.tv_usec = 10000 * (tout % 100);
- tdelay.it_interval.tv_sec = 0;
- tdelay.it_interval.tv_usec = 0;
-
- if (sigaction (SIGALRM, &act, &oact) < 0)
- {
- perror ("sigaction(tmlnk)");
- exit (EXIT_FAILURE);
- }
- if (setitimer (ITIMER_REAL, &tdelay, NULL) < 0)
- {
- perror ("setitimer(tmlnk)");
- exit (EXIT_FAILURE);
- }
-}
-
-void tmulk () {
- struct itimerval tdelay;
-
- tdelay.it_value.tv_sec = 0;
- tdelay.it_value.tv_usec = 0;
- tdelay.it_interval.tv_sec = 0;
- tdelay.it_interval.tv_usec = 0;
-
- if (setitimer (ITIMER_REAL, &tdelay, NULL) < 0)
- {
- perror ("setitimer(tmulk)");
- exit (EXIT_FAILURE);
- }
- if (sigaction (SIGALRM, &oact, NULL) < 0)
- {
- perror ("sigaction(tmulk)");
- exit (EXIT_FAILURE);
- }
-}
-
-#ifndef MRP
-rp_calib_params_t rp_calib_params; /** Pointer to externally defined calibration parameters. */ rp_calib_params_t *gen_calib_params = NULL;
-#endif
-int daq_init (char * buff) {
-#ifdef DEBUG
- fprintf (stderr, "Server: init\n");
-#endif
- int * hdr = (int *) buff;
- int delay = hdr[0];
- int decimation = hdr[1];
- float threshold_voltage = hdr[2]/1000.;
- fprintf(stderr, "delay = %d\tdecimation = %d\tthreshold = %f\n", delay, decimation, threshold_voltage);
-
-/*
-
- rp_default_calib_params(&rp_calib_params);
- gen_calib_params = &rp_calib_params;
- if(rp_read_calib_params(gen_calib_params) < 0) {
- fprintf(stderr, "rp_read_calib_params() failed, using default"
- " parameters\n");
- }
-
-*/
-
- // use this to acquire calibrated offset: int offset = gen_calib_params->fe_ch1_dc_offs;
-#ifdef MRP
- if(rp_Init() != RP_OK){
- fprintf(stderr, "Rp api init failed!\n");
- }
- rp_AcqReset();
- rp_AcqSetDecimation(decimation);
- const int c[2] = {RP_CH_1, RP_CH_2};
- rp_AcqSetTriggerLevel(c[0],threshold_voltage); //Trig level is set in Volts while in SCPI
- rp_AcqSetTriggerLevel(c[1],threshold_voltage);
- rp_AcqSetTriggerDelay(delay);
- return 0;
-#else
- // initialization
- int start = osc_fpga_init();
- if(start)
- {
- printf("osc_fpga_init didn't work, retval = %d",start);
- return -1;
- }
-
- // set acquisition parameters
- osc_fpga_set_trigger_delay(delay);
- g_osc_fpga_reg_mem->data_dec = decimation;
- osc_fpga_reset();
- g_osc_fpga_reg_mem->chb_thr = osc_fpga_cnv_v_to_cnt(threshold_voltage); //sets trigger voltage
-#endif
- fprintf(stderr, "%s : %d\n", __FILE__, __LINE__);
- return 0;
-}
-
-int daq_end () {
-#ifdef DEBUG
- fprintf (stderr, "Server: end\n");
-#endif
-#ifdef MRP
- rp_Release();
-#else
- osc_fpga_exit();
-#endif
- return 0;
-}
-
-int daq_clear () {
-#ifdef DEBUG
- fprintf (stderr, "Server: clear\n");
-#endif
- return 0;
-}
-
-
-int16_t chdata[16*1024];
-float * chfdata = (float *) chdata;
-int daq_run (const char *par, char ** data, int *maxlen)
-
-{
-
- int *data_buf;
- int neve;
-
- unsigned short *sbuff = (unsigned short *) (par);
- unsigned short maxeve = sbuff[0];
- unsigned short nsamples = sbuff[1];
- unsigned short tout = sbuff[2];
- unsigned char trigger = par[6];
- unsigned char chmask = par[7];
- clock_t t,t0;
- neve = 0;
-
- t0=clock();
- int eventsize = 0;
- if (chmask & 0x1) eventsize += (nsamples+2);
- if (chmask & 0x2) eventsize += (nsamples+2);
- eventsize+=4;
- int required_size = eventsize * maxeve+3;
-
-#ifdef DEBUG
- time_t mtime;
- time(&mtime);
- fprintf (stderr, "daq_run:\tmaxeve %d\tnsamples=%d\ttimeout=%d\ttrigger=%d\tchmask=%d\t%s", maxeve ,nsamples,tout,trigger,chmask, ctime(&mtime)); //
-#endif
-
-
- if (required_size > *maxlen ) {
- free (*data);
- *data = (char *) malloc(required_size *sizeof(int));
- fprintf(stderr, "New Buffer with size %d allocated. Old size %d\n", required_size, *maxlen);
- *maxlen = required_size;
- }
-
- int *ibuf = (int *) (*data);
-
-
- data_buf = ibuf + 3;
- const int sleeptime = 135*nsamples/16386; //135 us for 16386 samples and to fill the 16k ADC buffer/
-
- for (int ieve=0; ieve < maxeve; ieve++)
- {
-
-#ifdef MRP
-
-rp_AcqStart();
-usleep(sleeptime);
-rp_AcqSetTriggerSrc(trigger);
-timer_out = FALSE;
-tmlnk (tout);
-rp_acq_trig_src_t source;
-do {
- rp_AcqGetTriggerSrc(&source);
- //printf("TRG %d src %d\n", trigger, source);
- if (timer_out || ctrl_c) break;
-} while (source == trigger);
-
-tmulk ();
-usleep(sleeptime);
-
-
-#else
-
- osc_fpga_arm_trigger();
- usleep(sleeptime);
- osc_fpga_set_trigger(trigger);
-
- while (g_osc_fpga_reg_mem->trig_source != 0){
- if (timer_out || ctrl_c) break;
- }
- // with this loop the program waits until the acquistion is completed before continue.
- int trig_ptr = g_osc_fpga_reg_mem->wr_ptr_trigger; // get pointer to mem. adress where trigger was met
- int * ch_signal[2];
- osc_fpga_get_sig_ptr(&ch_signal[0], &ch_signal[1]);
-#endif
- *(data_buf++) = 0x2;
- *(data_buf++) = chmask;
-
- for (int id = 0;id<2;id++){
- if ( !(chmask & (1 << id)) ) continue;
-
- *(data_buf++) = id;
- *(data_buf++) = nsamples;
-#ifdef MRP
- const int c[2] = {RP_CH_1, RP_CH_2};
- unsigned int isamples = nsamples;
- rp_AcqGetLatestDataV(c[id], &isamples, (float *) data_buf );
- data_buf+=nsamples;
-#else
-
- const int BUF = 16*1024;
- const int offset = 0;
- if (trig_ptr > (BUF-nsamples)) // Enter logic to transition from end to beginning of cha_signal buffer.
- {
- for (int i=trig_ptr;i<BUF;i++) *(data_buf++) = ch_signal[id][i]-offset;
- for (int i=0;i<nsamples-(BUF-trig_ptr);i++) *(data_buf++) = ch_signal[id][i]-offset;
- }
- else // Enter simple logic to send sampleSize from trigger point
- {
- for (int i=0;i<nsamples;i++) *(data_buf++) = ch_signal[id][trig_ptr + i]-offset;
- }
-#endif
- }
- *(data_buf++) = 0x3;
- *(data_buf++) = neve;
- neve++;
- if (ieve+1 % 500 == 0) fprintf(stderr, "Event %d\n", ieve);
- if (timer_out) break;
-
- }
-
-
-
- int *len = ibuf;
- int *nev = ibuf + 1;
- float *dt = (float *)(ibuf + 2);
-
- *len = (data_buf-len)*sizeof(int);
- *nev = neve;
- t = clock();
- *dt = t-t0;
- *dt /= CLOCKS_PER_SEC;
-
- return *len;
-}
-
-#define MAXLEN 0XFFFF
-struct RUNHDR {
- unsigned short neve;
- unsigned short nsamples;
- unsigned short tout;
- unsigned char trigger;
- unsigned char mask;
- int nloops ;
- int data [MAXLEN];
-} ;
-
-
-struct INIHDR {
- int delay ;
- int decimation;
- int threshold;
-};
-
-
-int daq_help(char *fname, struct INIHDR * i, struct RUNHDR *r, int verbosity){
-
- printf("-o filename ... output filename %s\n", fname);
- printf("-v verbose ... verbosity %d\n", verbosity);
- printf("-b decimation ... decimation %d\n", i->decimation);
- printf("-i timeout ... interrupt timeout %d\n", r->tout);
- printf("-s nsamples ... number of samples %d\n", r->nsamples);
- printf("-d delay ... delay %d\n", i->delay);
- printf("-t trigger ... trigger type %d\n", r->trigger);
- printf("-l level ... trigger level %f\n", i->threshold*0.001);
- printf("-m mask ... channel mask %d\n", r->mask );
- printf("-n neve ... number of events per call %d\n", r->neve);
- printf("-r nloops ... number of calls %d\n", r->nloops);
- return 0;
-}
-
-
-
-int daq_main( int argc , char ** argv) {
- // intercept routine
- if (signal (SIGINT, SigInt) == SIG_ERR) {
- perror ("sigignore");
- }
-
-
- char filename[0xFF]="";
-
-
-struct INIHDR inihdr = {
- .decimation = 1,
- .threshold = 100,
- .delay = 1024
-};
-
-
-
-struct RUNHDR runhdr;
-
-
- runhdr.neve =10000;
- runhdr.nsamples = 1024;
- runhdr.tout = 1000;
- runhdr.trigger = 1;
- runhdr.mask = 0x1;
- runhdr.nloops = 1;
-
- int verbose = 0;
- int argdata = 0;
-
- if (argc <2) {
- daq_help(filename, &inihdr, &runhdr, verbose);
- exit(-1);
- }
-
- opterr = 0;
- int c;
- while ((c = getopt (argc, argv, "o:v:b:i:s:d:t:l:m:n:r:h")) != -1)
- switch (c) {
- case 'o':
- sprintf(filename,"%s", optarg );
- break; // output
- case 'v':
- verbose = strtoul (optarg,NULL,0);
- break; // verbosity
- case 'b':
- inihdr.decimation = strtoul (optarg,NULL,0);
- break;
- case 'i':
- runhdr.tout = strtoul (optarg,NULL,0);
- break;
- case 's':
- runhdr.nsamples = strtoul (optarg,NULL,0);
- break;
- case 'd':
- inihdr.delay = strtoul (optarg,NULL,0);
- break;
- case 't':
- runhdr.trigger = strtoul (optarg,NULL,0);
- break;
- case 'm':
- runhdr.mask = strtoul (optarg,NULL,0);
- break;
- case 'n':
- runhdr.neve = atoi (optarg);
- break;
- case 'r':
- runhdr.nloops = atoi (optarg);
- break;
- case 'l':
- inihdr.threshold = (int) (1000*atof (optarg));
- break;
- case 'h':
- daq_help(filename, &inihdr, &runhdr, verbose);
- break;
- case '?':
- if (optopt == 'c')
- fprintf (stderr, "Option -%c requires an argument.\n", optopt);
- else if (isprint (optopt))
- fprintf (stderr, "Unknown option `-%c'.\n", optopt);
- else
- fprintf (stderr,
- "Unknown option character `\\x%x'.\n",
- optopt);
- return 1;
- default:
- abort ();
- }
- for (int i=optind; i<argc; i++) argdata = strtoul (argv[i],NULL,0);
- if (verbose) daq_help(filename, &inihdr, &runhdr, verbose);
-
- printf("argdata %d nloops %d\n",argdata,runhdr.nloops);
-
- daq_init((char *)&inihdr);
- FILE *fp=NULL;
- if (strlen(filename)>0) fp = fopen(filename, "wb");
-
-
- int maxlen = MAXLEN;
- char *data = (char *) malloc(maxlen * sizeof(int));
- time_t t,tstart;
- time(&tstart);
-
- for (int i=0;i< runhdr.nloops;i++){
- int nb =daq_run((const char*) &runhdr, &data, &maxlen);
- if (ctrl_c) break;
- time(&t);
- fprintf(stderr, "Loop %d dt=%d s\n", i, (int)(t-tstart));
-
- if (fp) {
- fprintf(stderr, "Writing %d to %s", nb, filename);
- fwrite(data, 1, nb, fp);
- }
-
- }
- time(&t);
- fprintf(stderr, "Total events %d in %d s\n", runhdr.nloops*runhdr.neve, (int)(t-tstart));
- if (fp) fclose(fp);
- if (data!=NULL) free(data);
- return 0;
-}