| /cvi/RedPitaya/sockserv/daq.c |
|---|
| 0,0 → 1,445 |
| #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; |
| } |
| /cvi/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/RedPitaya/sockserv/daq.h |
|---|
| 0,0 → 1,10 |
| #ifndef DAQ_H |
| #define DAQ_H |
| int daq_init (char * buff); |
| 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/RedPitaya/sockserv/sockserv.c |
|---|
| 0,0 → 1,209 |
| /* |
| 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; |
| } |
| /cvi/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/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/RedPitaya/sockserv/daqprofile.sh |
|---|
| 0,0 → 1,0 |
| export LD_LIBRARY_PATH=/opt/redpitaya/lib/ |
| /cvi/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/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/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 |
| /cvi/instr/RedPitaya/sockserv/Makefile |
|---|
| File deleted |
| /cvi/instr/RedPitaya/sockserv/daqprofile.sh |
|---|
| File deleted |
| /cvi/instr/RedPitaya/sockserv/calib.h |
|---|
| File deleted |
| /cvi/instr/RedPitaya/sockserv/sockserv.c |
|---|
| File deleted |
| /cvi/instr/RedPitaya/sockserv/fpga_osc.c |
|---|
| File deleted |
| /cvi/instr/RedPitaya/sockserv/daq.c |
|---|
| File deleted |
| /cvi/instr/RedPitaya/sockserv/fpga_osc.h |
|---|
| File deleted |
| /cvi/instr/RedPitaya/sockserv/calib.c |
|---|
| File deleted |
| /cvi/instr/RedPitaya/sockserv/daq.h |
|---|
| File deleted |
| /cvi/instr/RedPitaya/sockserv/version.h |
|---|
| File deleted |
| Property changes: |
| Deleted: svn:executable |