Subversion Repositories f9daq

Compare Revisions

Ignore whitespace Rev 227 → Rev 228

/cvi/instr/RedPitaya/sockserv/Makefile
0,0 → 1,96
#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
/cvi/instr/RedPitaya/sockserv/calib.c
0,0 → 1,105
/**
* $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;
}
/cvi/instr/RedPitaya/sockserv/calib.h
0,0 → 1,45
/**
* $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
/cvi/instr/RedPitaya/sockserv/daq.c
0,0 → 1,432
#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; {
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, int nb) {
#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;
}
 
int daq_run (const char *par, char ** data, int *maxlen)
 
{
int *data_buf;
int neve;
 
unsigned short *sbuff = (unsigned short *) (par+4);
unsigned short maxeve = sbuff[0];
unsigned short nsamples = sbuff[1];
unsigned short tout = sbuff[2];
unsigned char trigger = par[10];
unsigned char chmask = par[11];
 
neve = 0;
timer_out = FALSE;
tmlnk (tout);
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
fprintf (stderr, "daq_run:\tmaxeve %d\tnsamples=%d\ttimeout=%d\ttrigger=%d\tchmask=%d\n", maxeve ,nsamples,tout,trigger,chmask); //
//fprintf (stderr, "required %d reserved %d\n", required_size,*maxlen);
#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);
 
rp_acq_trig_state_t state = RP_TRIG_STATE_TRIGGERED;
do {
rp_AcqGetTriggerSrc(&state);
} while (state == RP_TRIG_STATE_WAITING );
//while(rp_AcqSetTriggerState(trigger));
 
#else
 
osc_fpga_arm_trigger();
usleep(sleeptime);
osc_fpga_set_trigger(trigger);
 
while (g_osc_fpga_reg_mem->trig_source != 0){}
// 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_AcqGetOldestDataV(c[id], &isamples, (float *) data_buf);
#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 % 1000 == 0) printf("Event %d\n", ieve);
if (timer_out) break;
 
}
 
tmulk ();
int *len = ibuf;
int *nev = ibuf + 1;
int *recid = ibuf + 2;
*len = (data_buf-len)*sizeof(int);
*nev = neve;
*recid = 0xFAF5;
return *len;
}
 
#define MAXLEN 0XFFFF
struct RUNHDR {
int len;
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.len = sizeof(struct 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, sizeof(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;
}
/cvi/instr/RedPitaya/sockserv/daq.h
0,0 → 1,10
#ifndef DAQ_H
#define DAQ_H
 
int daq_init (char * buff, int len);
int daq_clear ();
int daq_end ();
int daq_run (const char *par, char ** buff, int *maxlen);
int daq_main (int argc, char **argv);
 
#endif
/cvi/instr/RedPitaya/sockserv/daqprofile.sh
0,0 → 1,0
export LD_LIBRARY_PATH=/opt/redpitaya/lib/
/cvi/instr/RedPitaya/sockserv/fpga_osc.c
0,0 → 1,564
/**
* $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;
}
 
/cvi/instr/RedPitaya/sockserv/fpga_osc.h
0,0 → 1,261
/**
* $Id: fpga_osc.h 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.
*/
 
#ifndef __FPGA_OSC_H
#define __FPGA_OSC_H
 
#include <stdint.h>
 
/** @defgroup fpga_osc_h fpga_osc_h
* @{
*/
 
/** Base OSC FPGA address */
#define OSC_FPGA_BASE_ADDR 0x40100000
/** Base OSC FPGA core size */
#define OSC_FPGA_BASE_SIZE 0x30000
/** OSC FPGA input signal buffer length */
#define OSC_FPGA_SIG_LEN (16*1024)
/** OSC FPGA ARM bit in configuration register */
#define OSC_FPGA_CONF_ARM_BIT 1
/** OSC FPGA reset bit in configuration register */
#define OSC_FPGA_CONF_RST_BIT 2
 
/** OSC FPGA trigger source register mask */
#define OSC_FPGA_TRIG_SRC_MASK 0x00000007
/** OSC FPGA Channel A threshold register mask */
#define OSC_FPGA_CHA_THR_MASK 0x00003fff
/** OSC FPGA Channel B threshold register mask */
#define OSC_FPGA_CHB_THR_MASK 0x00003fff
/** OSC FPGA trigger delay register register mask */
#define OSC_FPGA_TRIG_DLY_MASK 0xffffffff
/** OSC FPGA data decimation mask */
#define OSC_FPGA_DATA_DEC_MASK 0x0001ffff
 
/** OSC FPGA Channel A input signal buffer offset */
#define OSC_FPGA_CHA_OFFSET 0x10000
/** OSC FPGA Channel B input signal buffer offset */
#define OSC_FPGA_CHB_OFFSET 0x20000
 
/** @brief OSC FPGA registry structure.
*
* This structure is direct image of physical FPGA memory. When accessing it all
* reads/writes are performed directly from/to FPGA OSC core.
*/
typedef struct osc_fpga_reg_mem_s {
/** @brief Offset 0x00 - configuration register
*
* Configuration register (offset 0x00):
* bit [0] - arm_trigger
* bit [1] - rst_wr_state_machine
* bits [31:2] - reserved
*/
uint32_t conf;
 
/** @brief Offset 0x04 - trigger source register
*
* Trigger source register (offset 0x04):
* bits [ 2 : 0] - trigger source:
* 1 - trig immediately
* 2 - ChA positive edge
* 3 - ChA negative edge
* 4 - ChB positive edge
* 5 - ChB negative edge
* 6 - External trigger 0
* 7 - External trigger 1
* bits [31 : 3] -reserved
*/
uint32_t trig_source;
 
/** @brief Offset 0x08 - Channel A threshold register
*
* Channel A threshold register (offset 0x08):
* bits [13: 0] - ChA threshold
* bits [31:14] - reserved
*/
uint32_t cha_thr;
 
/** @brief Offset 0x0C - Channel B threshold register
*
* Channel B threshold register (offset 0x0C):
* bits [13: 0] - ChB threshold
* bits [31:14] - reserved
*/
uint32_t chb_thr;
 
/** @brief Offset 0x10 - After trigger delay register
*
* After trigger delay register (offset 0x10)
* bits [31: 0] - trigger delay
* 32 bit number - how many decimated samples should be stored into a buffer.
* (max 16k samples)
*/
uint32_t trigger_delay;
 
/** @brief Offset 0x14 - Data decimation register
*
* Data decimation register (offset 0x14):
* bits [16: 0] - decimation factor, legal values:
* 1, 8, 64, 1024, 8192 65536
* If other values are written data is undefined
* bits [31:17] - reserved
*/
uint32_t data_dec;
 
/** @brief Offset 0x18 - Current write pointer register
*
* Current write pointer register (offset 0x18), read only:
* bits [13: 0] - current write pointer
* bits [31:14] - reserved
*/
uint32_t wr_ptr_cur;
/** @brief Offset 0x1C - Trigger write pointer register
*
* Trigger write pointer register (offset 0x1C), read only:
* bits [13: 0] - trigger pointer (pointer where trigger was detected)
* bits [31:14] - reserved
*/
uint32_t wr_ptr_trigger;
/** @brief ChA & ChB hysteresis - both of the format:
* bits [13: 0] - hysteresis threshold
* bits [31:14] - reserved
*/
uint32_t cha_hystersis;
uint32_t chb_hystersis;
 
/** @brief
* bits [0] - enable signal average at decimation
* bits [31:1] - reserved
*/
uint32_t other;
uint32_t reseved;
/** @brief ChA Equalization filter
* bits [17:0] - AA coefficient (pole)
* bits [31:18] - reserved
*/
uint32_t cha_filt_aa;
/** @brief ChA Equalization filter
* bits [24:0] - BB coefficient (zero)
* bits [31:25] - reserved
*/
uint32_t cha_filt_bb;
/** @brief ChA Equalization filter
* bits [24:0] - KK coefficient (gain)
* bits [31:25] - reserved
*/
uint32_t cha_filt_kk;
/** @brief ChA Equalization filter
* bits [24:0] - PP coefficient (pole)
* bits [31:25] - reserved
*/
uint32_t cha_filt_pp;
 
/** @brief ChB Equalization filter
* bits [17:0] - AA coefficient (pole)
* bits [31:18] - reserved
*/
uint32_t chb_filt_aa;
/** @brief ChB Equalization filter
* bits [24:0] - BB coefficient (zero)
* bits [31:25] - reserved
*/
uint32_t chb_filt_bb;
/** @brief ChB Equalization filter
* bits [24:0] - KK coefficient (gain)
* bits [31:25] - reserved
*/
uint32_t chb_filt_kk;
/** @brief ChB Equalization filter
* bits [24:0] - PP coefficient (pole)
* bits [31:25] - reserved
*/
uint32_t chb_filt_pp;
/* ChA & ChB data - 14 LSB bits valid starts from 0x10000 and
* 0x20000 and are each 16k samples long */
} osc_fpga_reg_mem_t;
 
/** @} */
 
// TODO: Move to a shared folder and share with scope & spectrum.
/** Equalization & shaping filter coefficients */
typedef struct {
uint32_t aa;
uint32_t bb;
uint32_t pp;
uint32_t kk;
} ecu_shape_filter_t;
 
int osc_fpga_init(void);
int osc_fpga_exit(void);
 
void get_equ_shape_filter(ecu_shape_filter_t *filt, uint32_t equal,
uint32_t shaping, uint32_t gain);
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 osc_fpga_reset(void);
int osc_fpga_arm_trigger(void);
int osc_fpga_set_trigger(uint32_t trig_source);
int osc_fpga_set_trigger_delay(uint32_t trig_delay);
 
/* Returns 0 if no trigger, 1 if trigger */
int osc_fpga_triggered(void);
 
/* Returns pointer to the ChA and ChB signals (of length OSC_FPGA_SIG_LEN) */
int osc_fpga_get_sig_ptr(int **cha_signal, int **chb_signal);
 
/* Returns signal pointers from the FPGA */
int osc_fpga_get_wr_ptr(int *wr_ptr_curr, int *wr_ptr_trig);
 
/* Returnes signal content */
/* various constants */
extern const float c_osc_fpga_smpl_freq;
extern const float c_osc_fpga_smpl_period;
 
/* helper conversion functions */
/* Convert correct value for FPGA trigger source from trig_immediately,
* trig_source and trig_edge from application params.
*/
int osc_fpga_cnv_trig_source(int trig_imm, int trig_source, int trig_edge);
/* Converts time_range parameter (0-5) to decimation factor */
int osc_fpga_cnv_time_range_to_dec(int time_range);
/* Converts time in [s] to ADC samples (depends on decimation) */
int osc_fpga_cnv_time_to_smpls(float time, int dec_factor);
/* Converts voltage in [V] to ADC counts */
int osc_fpga_cnv_v_to_cnt(float voltage);
/* Converts ADC ounts to [V] */
float osc_fpga_cnv_cnt_to_v(int cnts);
 
/* Debug - dump to stderr current parameter settings (leave out data) */
void osc_fpga_dump_regs(void);
 
/* debugging - will be removed */
extern osc_fpga_reg_mem_t *g_osc_fpga_reg_mem;
extern int g_osc_fpga_mem_fd;
int __osc_fpga_cleanup_mem(void);
 
#endif /* __FPGA_OSC_H*/
/cvi/instr/RedPitaya/sockserv/sockserv.c
0,0 → 1,223
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include "daq.h"
/* #define DEBUG */
 
#define PORT 9930
#define EXIT_FAILURE 1
 
int make_socket (port)
unsigned short int port;
{
int sock;
struct sockaddr_in name;
 
/* create the socket. */
sock = socket (AF_INET, SOCK_STREAM, 0);
if (sock < 0)
{
perror ("socket");
exit (EXIT_FAILURE);
}
/* give the socket name */
name.sin_family = AF_INET;
name.sin_port = htons (port);
name.sin_addr.s_addr = htonl (INADDR_ANY);
if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0)
{
perror ("bind");
exit (EXIT_FAILURE);
}
return sock;
}
 
void write_socket (sock_num, buff, len)
int sock_num, len;
char *buff;
{
int status;
 
do
{
if (0 > (status = write (sock_num, buff, len)))
{
perror ("\nwrite(write_socket)");
exit (EXIT_FAILURE);
}
len -= status;
buff += status;
}
while (len);
}
 
void read_socket (sock_num, buff, len)
int sock_num, len;
char *buff;
{
int status;
 
do
{
if (0 > (status = read (sock_num, buff, len)))
{
perror ("\nread(read_socket)");
exit (EXIT_FAILURE);
}
len -= status;
buff += status;
}
while (len);
}
 
 
 
int main (int argc, char ** argv)
{
int sock_org, sock_cam, sock_new;
int bufsize = 10000000;
int recvdata[0xFF];
char *data, status, connected = 0;
char msg;
if (argc >1) return daq_main(argc, argv);
 
data = malloc(sizeof(int) * bufsize);
int *idata = (int*)data;
fd_set active_fd_set, read_fd_set;
struct sockaddr_in clientname;
size_t size;
 
 
/* map camac memory */
//map_camac ();
 
/* Create the socket and set it up to accept connections */
sock_org = make_socket (PORT);
if (listen (sock_org, 1) < 0)
{
perror ("listen");
exit (EXIT_FAILURE);
}
/* Initialize the set of active sockets */
FD_ZERO (&active_fd_set);
FD_SET (sock_org, &active_fd_set);
 
while (1)
{
read_fd_set = active_fd_set;
if (select (32, &read_fd_set, 0, 0, 0) <0)
{
perror ("select");
exit (EXIT_FAILURE);
}
if (FD_ISSET (sock_org, &read_fd_set))
{
size = sizeof (clientname);
sock_new = accept (sock_org, (struct sockaddr *) &clientname, &size);
if (sock_new < 0)
{
perror ("accept");
exit (EXIT_FAILURE);
}
fprintf (stderr, "Server: connect from host %s, port %hd.\n",
inet_ntoa (clientname.sin_addr),
ntohs (clientname.sin_port));
if (connected)
{
msg = 0;
status = send (sock_new, &msg, 1, 0);
{
perror ("send");
exit (EXIT_FAILURE);
}
close (sock_new);
}
else
{
msg = 1;
status = send (sock_new, &msg, 1, 0);
if (status < 0)
 
 
{
perror ("send");
exit (EXIT_FAILURE);
}
sock_cam = sock_new;
FD_SET (sock_cam, &active_fd_set);
connected = 1;
}
}
else
{
/* Data ariving on an already-connected socket. */
status = recv (sock_cam, &msg, 1, 0);
if (status < 0)
{
perror ("recv");
exit (EXIT_FAILURE);
}
if (status == 0) msg = 0;
 
#ifdef DEBUG
fprintf (stderr, "Server: Cmd(%d): %d\n", status, msg);
#endif
 
switch (msg)
{
case 0:
fprintf (stderr, "Server: disconnecting\n");
close (sock_cam);
FD_CLR (sock_cam, &active_fd_set);
connected = 0;
daq_end();
break;
case 1:
read_socket (sock_cam, &data[8], 12);
daq_init (&data[8], idata[0]);
fprintf (stderr, "Server: Init finished\n");
break;
case 2:
daq_clear ();
break;
case 3:
fprintf (stderr, "Server: Run Start\n");
 
read_socket (sock_cam, (char *) &recvdata[1], 8);
daq_run ((const char *) recvdata, &data, &bufsize );
idata = (int*)data;
#ifdef DEBUG
fprintf (stderr, "Server: Run end: %d\n", idata[0]);
#endif
 
write_socket (sock_cam, &msg, 1);
 
#ifdef DEBUG
fprintf (stderr, "Server: Data ready(%d): %d\n", status, msg);
#endif
 
break;
case 4:
write_socket (sock_cam, &msg, 1);
write_socket (sock_cam, data, idata[0]);
 
#ifdef DEBUG
fprintf (stderr, "Server: Data sent: %d, %d, %d\n",
idata[0], idata[1], idata[2]);
#endif
 
break;
default:
fprintf (stderr, "Server: unknown command -> exiting...\n");
exit (EXIT_FAILURE);
}
}
}
if (data !=NULL) free(data);
}
/cvi/instr/RedPitaya/sockserv/version.h
0,0 → 1,34
/**
* $Id: $
*
* @brief Red Pitaya simple version strings. To be embedded in binaries
* at build time for SW traceability.
*
* @Author Ales Bardorfer <ales.bardorfer@redpitaya.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 VERSION_H
#define VERSION_H
 
#define XSTR(s) STR(s)
#define STR(s) #s
#ifndef VERSION
#define VERSION_STR "0.00-0000"
#else
#define VERSION_STR XSTR(VERSION)
#endif
#ifndef REVISION
#define REVISION_STR "unknown"
#else
#define REVISION_STR XSTR(REVISION)
#endif
 
#endif /* VERSION_H */
Property changes:
Added: svn:executable