First compiling commit
This commit is contained in:
@@ -0,0 +1 @@
|
||||
build
|
||||
@@ -0,0 +1,3 @@
|
||||
[submodule "midas_lan_gpib"]
|
||||
path = midas_lan_gpib
|
||||
url = git@gitea.psi.ch:lin-midas-drivers/midas_lan_gpib.git
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
cmake_minimum_required(VERSION 3.03)
|
||||
|
||||
project(expmag VERSION 0.1)
|
||||
|
||||
add_compile_options(
|
||||
-Wall
|
||||
-Wformat=2
|
||||
-Wno-format-nonliteral
|
||||
-Wno-strict-aliasing
|
||||
-Wuninitialized
|
||||
-Wno-unused-function
|
||||
)
|
||||
|
||||
option(
|
||||
BUILD_FRONTEND
|
||||
"If ON, build the default frontend executable"
|
||||
OFF
|
||||
)
|
||||
|
||||
set(
|
||||
TCPIP_DRIVER_DIR
|
||||
$ENV{MIDASSYS}/drivers/bus/tcpip.cxx
|
||||
CACHE STRING
|
||||
"path to tcpip driver that should be used"
|
||||
)
|
||||
|
||||
set(
|
||||
DRIVERS
|
||||
$ENV{MIDASSYS}/drivers/class/generic.cxx
|
||||
)
|
||||
|
||||
set(SYS_LIBS
|
||||
pthread
|
||||
util
|
||||
rt
|
||||
dl
|
||||
)
|
||||
|
||||
link_directories($ENV{MIDASSYS}/lib)
|
||||
# Links to libmfe.a and libmidas.a
|
||||
set(MIDAS_LIBS
|
||||
mfe
|
||||
midas
|
||||
mscb
|
||||
)
|
||||
|
||||
set(LIBS ${SYS_LIBS} ${MIDAS_LIBS})
|
||||
|
||||
add_subdirectory(midas_lan_gpib)
|
||||
|
||||
################################################################################
|
||||
## make tcpip library configurable
|
||||
################################################################################
|
||||
|
||||
if(IS_DIRECTORY ${TCPIP_DRIVER_DIR})
|
||||
add_subdirectory(
|
||||
# TODO not sure, should it be a submodule? does it really make sense to
|
||||
# separate everything?
|
||||
${TCPIP_DRIVER_DIR} ./bus/tcpip
|
||||
)
|
||||
|
||||
set(
|
||||
LIBS
|
||||
${LIBS}
|
||||
tcpip
|
||||
)
|
||||
else()
|
||||
set(
|
||||
DRIVERS
|
||||
${DRIVERS}
|
||||
${TCPIP_DRIVER_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
################################################################################
|
||||
## Device Library
|
||||
################################################################################
|
||||
|
||||
add_library(
|
||||
expmag
|
||||
device/expmag.cxx
|
||||
device/spline.cxx
|
||||
${DRIVERS}
|
||||
)
|
||||
|
||||
set_property(
|
||||
TARGET
|
||||
expmag
|
||||
PROPERTY
|
||||
CXX_STANDARD 11
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
expmag
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
PRIVATE
|
||||
$ENV{MIDASSYS}/drivers
|
||||
$ENV{MIDASSYS}/include
|
||||
# This is redundant if MIDASSYS =/ Midas repo, since in that case the Midas
|
||||
# CMakeLists.txt copies the needed file mstrlcpy.h into $ENV{MIDASSYS}/include
|
||||
# But it doesn't do any harm here, so it is kept.
|
||||
$ENV{MIDASSYS}/include/mscb
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
expmag
|
||||
PUBLIC
|
||||
midas_lan_gpib
|
||||
${LIBS}
|
||||
)
|
||||
|
||||
################################################################################
|
||||
## Test Frontend
|
||||
################################################################################
|
||||
|
||||
if(${BUILD_FRONTEND})
|
||||
|
||||
add_executable(
|
||||
expmag_fe
|
||||
frontend/expmag_scfe.cxx
|
||||
)
|
||||
|
||||
set_property(
|
||||
TARGET
|
||||
expmag_fe
|
||||
PROPERTY
|
||||
CXX_STANDARD 11
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
expmag_fe
|
||||
PRIVATE
|
||||
$ENV{MIDASSYS}/drivers
|
||||
$ENV{MIDASSYS}/include
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
expmag_fe
|
||||
expmag
|
||||
)
|
||||
|
||||
endif()
|
||||
@@ -0,0 +1,70 @@
|
||||
# Main experimental magnet PS
|
||||
|
||||
This repository contains the driver code and Midas frontend for the main
|
||||
experimental magnet PS.
|
||||
|
||||
TODO: Document flag EPICSGFA
|
||||
|
||||
## Requirements
|
||||
|
||||
Requires a Midas installation with the environment variable `MIDASSYS` pointing
|
||||
to the built Midas artifacts and headers.
|
||||
|
||||
## Build
|
||||
|
||||
Clone this repository, enter the cloned directory, and then build via CMake.
|
||||
|
||||
```bash
|
||||
cmake -S "$(pwd)" -B <directory-to-build-in> -DBUILD_FRONTEND=ON
|
||||
cmake --build <directory-to-build-in> --clean-first -- -j8
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
<directory-to-build-in>/expmag_scfe -e <instrument-name>
|
||||
```
|
||||
|
||||
## Including in Custom Frontend
|
||||
To include this driver in a custom frontend, you should ensure the environment
|
||||
variable `MIDASSYS` points to your system install and include a snippet in your
|
||||
`CMakeLists.txt` similar to the following:
|
||||
|
||||
```CMake
|
||||
# If the path to the expmag repository is outside of the frontend
|
||||
# repository, you also need to provide a location for the expmag
|
||||
# artifacts as a second argument to `add_subdirectory`
|
||||
# e.g. `./device/expmag`
|
||||
add_subdirectory(
|
||||
<path-to-expmag-repository>
|
||||
)
|
||||
|
||||
add_executable(
|
||||
<frontend-name>
|
||||
<frontend-code-path-1>
|
||||
<frontend-code-path-2>
|
||||
:
|
||||
)
|
||||
|
||||
set_property(
|
||||
TARGET
|
||||
<frontend-name>
|
||||
PROPERTY
|
||||
CXX_STANDARD 11
|
||||
)
|
||||
|
||||
target_include_directories(
|
||||
<frontend-name>
|
||||
PRIVATE
|
||||
$ENV{MIDASSYS}/drivers
|
||||
$ENV{MIDASSYS}/include
|
||||
)
|
||||
|
||||
target_link_libraries(
|
||||
<frontend-name>
|
||||
expmag
|
||||
<additional-library-1>
|
||||
<additional-library-2>
|
||||
:
|
||||
)
|
||||
```
|
||||
+7361
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,10 @@
|
||||
/********************************************************************\
|
||||
|
||||
Created by: RA35
|
||||
|
||||
Contents: Device driver function declarations for experimental magnets device
|
||||
|
||||
|
||||
\********************************************************************/
|
||||
|
||||
INT expmag(INT cmd, ...);
|
||||
@@ -0,0 +1,741 @@
|
||||
/********************************************************************\
|
||||
|
||||
Name: spline.c
|
||||
Created by: RA95
|
||||
|
||||
Contents: Routines to perform cubic spline interpolation
|
||||
|
||||
Revision 1.2 2017/01/26 07:45:52 raselli
|
||||
Fixed compilation errors
|
||||
|
||||
Revision 1.1 2017/01/26 07:37:25 raselli
|
||||
Original bulk muSR Midas 1.9.5 version
|
||||
|
||||
Revision 1.8 2016/09/09 13:14:40 raselli
|
||||
Bulk musr 09-SEP-2016
|
||||
|
||||
Revision 1.0 2003/09/29 12:18:57 midas
|
||||
|
||||
Date Name Modification
|
||||
-----------------------------------------------------------------
|
||||
25-OCT-2003 RA95 Initial version
|
||||
09-JUN-2004 RA35 splines() interval search modified for descending
|
||||
x values of calibration data to handle reverse
|
||||
interpolation
|
||||
|
||||
\********************************************************************/
|
||||
|
||||
#define SPLIN_INF 1.0e36 /* infinite value */
|
||||
#define SPLIN_U6 (1.0/6.0) /* coefficient */
|
||||
#define SPLIN_EPSLN 1.0e-3 /* convergence limit */
|
||||
#define SPLIN_OG 1.0717968
|
||||
|
||||
#define ABS(a) ((a) >= 0.0)?(a):-(a)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include "midas.h"
|
||||
#include "spline.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
/* #define MIDEBUGD /* display information */
|
||||
/* #define MIDEBUG1 /* function calls and essential */
|
||||
/* #define MIDEBUG2 /* additional info */
|
||||
/* #define MIDEBUG3 /* exhaustive */
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
INT splineo(char *, INT *, double **, double **, BOOL);
|
||||
INT splinec(INT, double *, double *, double *, double *, double *, BOOL);
|
||||
INT splines(INT, double *, double *, double *, double *, double *,
|
||||
INT, double *, double *, BOOL);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
INT splineo(char *filename, INT *npoints, double **X, double **Y, BOOL verbose) {
|
||||
|
||||
/********************************************************************\
|
||||
|
||||
Routine: splineo
|
||||
|
||||
Purpose: open and process calibration file
|
||||
return number of data points and data points
|
||||
|
||||
Input:
|
||||
char *filename file containing interpolation input data
|
||||
BOOL verbose show information on display if TRUE
|
||||
|
||||
Output:
|
||||
INT *npoints address of number of data points read from file
|
||||
double **X address of pointer to X values
|
||||
double **Y address of pointer to corresponding Y values
|
||||
|
||||
Function value:
|
||||
INT SS_SUCCESS : Success
|
||||
|
||||
\********************************************************************/
|
||||
|
||||
INT ret;
|
||||
|
||||
#ifdef MIDEBUG1
|
||||
printf(">> splineo (%s)\n",filename);
|
||||
#endif
|
||||
|
||||
#ifdef MIDEBUGD
|
||||
verbose = TRUE;
|
||||
#endif
|
||||
|
||||
ret = CM_SUCCESS;
|
||||
|
||||
if ((filename != NULL) && (strlen(filename) > 0) && (npoints != NULL) &&
|
||||
(X != NULL) && (Y != NULL)) {
|
||||
FILE *pfile;
|
||||
|
||||
/* initialise return parameters */
|
||||
*npoints = 0;
|
||||
*X = NULL;
|
||||
*Y = NULL;
|
||||
|
||||
/* open and process calibration file */
|
||||
if ((pfile = fopen(filename,"r")) != NULL) {
|
||||
char line[255];
|
||||
INT i,n;
|
||||
INT len;
|
||||
double *x, *y;
|
||||
double xi, yi;
|
||||
|
||||
n = 0;
|
||||
x = NULL;
|
||||
y = NULL;
|
||||
|
||||
read_again: ;
|
||||
|
||||
/* process file */
|
||||
while (!feof(pfile)) {
|
||||
|
||||
/*
|
||||
* file contents
|
||||
* --------------
|
||||
! comment
|
||||
xxx.xxx yyy.yyy ! table of data pairs
|
||||
! x and y are separated by space
|
||||
! each pair is on a separate line
|
||||
! x values of table are continuous in
|
||||
! ascending order
|
||||
! y values are continuous
|
||||
*/
|
||||
|
||||
if (fgets(line,sizeof(line),pfile)!=NULL) {
|
||||
if ((len=strlen(line))>0) {
|
||||
#ifdef MIDEBUG3
|
||||
printf("last char : %d\n",line[len-1]);
|
||||
#endif
|
||||
/* remove cr & lf */
|
||||
while ((len >=0) && ((line[len-1] == '\x0a')||(line[len-1] == '\r')))
|
||||
line[--len] = '\0';
|
||||
|
||||
#ifdef MIDEBUG3
|
||||
printf("Line : >%s<\n",line);
|
||||
#endif
|
||||
/* remove comments */
|
||||
for(i=len-1;i>=0;i--)
|
||||
if (line[i] == '!') {
|
||||
line[i] = '\0';
|
||||
len=i;
|
||||
}
|
||||
#ifdef MIDEBUG3
|
||||
printf("comment removed : >%s<\n",line);
|
||||
#endif
|
||||
|
||||
/* remove trailing blanks */
|
||||
while ((len>0)&& isspace(line[len-1])) line[--len] = '\0';
|
||||
|
||||
#ifdef MIDEBUG3
|
||||
printf("trailing spaces removed : >%s<\n",line);
|
||||
#endif
|
||||
|
||||
/* remove leading blanks and multiple spaces */
|
||||
if (len > 0) {
|
||||
BOOL space;
|
||||
INT j;
|
||||
|
||||
j=-1;
|
||||
for(i=0,space=FALSE;i<len;i++){
|
||||
if (isspace(line[i])) {
|
||||
if ((!space)&&(j!=-1)) line[++j] = ' ';
|
||||
space = TRUE;
|
||||
} else {
|
||||
line[++j]=line[i];
|
||||
space = FALSE;
|
||||
}
|
||||
}
|
||||
line[++j] = '\0';
|
||||
len = strlen(line);
|
||||
#ifdef MIDEBUG3
|
||||
printf("multiple spaces removed : >%s<\n",line);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
|
||||
/* read values */
|
||||
if (sscanf(line,"%lf %lf",&xi,&yi)==2) {
|
||||
|
||||
/* store values */
|
||||
if (x != NULL) *(x+n) = xi;
|
||||
if (y != NULL) *(y+n) = yi;
|
||||
n++;
|
||||
|
||||
} else {
|
||||
cm_msg(MERROR,"splineo","ERROR reading x and y as floating point numbers.");
|
||||
ret = CM_SET_ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
#ifdef MIDEBUG2
|
||||
cm_msg(MERROR,"splineo","WARNING empty line in calibration file %s",
|
||||
filename);
|
||||
#endif
|
||||
}
|
||||
} else {
|
||||
if (ferror(pfile)) {
|
||||
cm_msg(MERROR,"splineo",
|
||||
"fgets error %d reading line from calibration file",errno);
|
||||
ret = CM_SET_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* any points found and data not allocated? */
|
||||
if ((n > 0) && (x == NULL)) {
|
||||
|
||||
/* allocate storage space */
|
||||
x = (double *) calloc(n,sizeof(double));
|
||||
y = (double *) calloc(n,sizeof(double));
|
||||
|
||||
n = 0; /* reset number of processed data pairs */
|
||||
|
||||
/* reposition to beginning of file (if data is now allocated) */
|
||||
if ( (x != NULL) && (y != NULL)) {
|
||||
fseek(pfile,0,SEEK_SET);
|
||||
goto read_again;
|
||||
}
|
||||
|
||||
if (x != NULL) free(x);
|
||||
if (y != NULL) free(y);
|
||||
x = NULL;
|
||||
y = NULL;
|
||||
|
||||
/* not able to allocate data */
|
||||
cm_msg(MERROR,"splineo","ERROR not able to allocate memory for x or y data");
|
||||
ret = SS_NO_MEMORY;
|
||||
|
||||
} else if (n==0) {
|
||||
cm_msg(MERROR,"splineo","ERROR no valid x y data in %s",filename);
|
||||
ret = CM_SET_ERROR;
|
||||
}
|
||||
|
||||
if (fclose(pfile) == EOF) {
|
||||
cm_msg(MERROR,"splineo","fclose error %d closing calibration file", errno);
|
||||
ret = CM_SET_ERROR;
|
||||
}
|
||||
|
||||
/* check values */
|
||||
if ((x != NULL)&&(y != NULL)) {
|
||||
if (n >= 3) {
|
||||
BOOL xcont,ycont,yasc;
|
||||
|
||||
xcont = TRUE;
|
||||
ycont = TRUE;
|
||||
|
||||
if (*y < *(y+n-1))
|
||||
yasc = TRUE;
|
||||
else
|
||||
yasc = FALSE;
|
||||
|
||||
for (i=0;i<n-1;i++) {
|
||||
|
||||
/* x steady ascending? */
|
||||
if (*(x+i) >= *(x+i+1)) xcont = FALSE;
|
||||
|
||||
/* y ascending or descending? */
|
||||
if (yasc) {
|
||||
if (*(y+i) >= *(y+i+1)) ycont = FALSE;
|
||||
} else {
|
||||
if (*(y+i) <= *(y+i+1)) ycont = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!xcont) {
|
||||
cm_msg(MERROR,"splineo",
|
||||
"X data points in calibration file %s are not continuously ascending",
|
||||
filename);
|
||||
ret = CM_SET_ERROR;
|
||||
}
|
||||
|
||||
if (!ycont) {
|
||||
cm_msg(MERROR,"splineo",
|
||||
"Non continuous Y data points in calibration file %s",filename);
|
||||
ret = CM_SET_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
cm_msg(MERROR,"splineo","Not enough data points in calibration file %s",
|
||||
filename);
|
||||
ret = CM_SET_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* everything OK? */
|
||||
if ((n >= 3) && (ret == CM_SUCCESS)) {
|
||||
|
||||
if (verbose) {
|
||||
printf("\n");
|
||||
for (i=0; i<n; i++)
|
||||
printf(" x[%2.2d] = % lf, y[%2.2d] = % lf\n",i+1,*(x+i),i+1,*(y+i));
|
||||
}
|
||||
|
||||
/* return number of points and data */
|
||||
*npoints = n;
|
||||
*X = x;
|
||||
*Y = y;
|
||||
|
||||
} else {
|
||||
|
||||
if (x != NULL) free(x);
|
||||
if (y != NULL) free(y);
|
||||
x = NULL;
|
||||
y = NULL;
|
||||
|
||||
}
|
||||
} else {
|
||||
if (errno == ENOENT)
|
||||
cm_msg(MERROR,"splineo","ERROR calibration file %s does not exist",
|
||||
filename);
|
||||
else
|
||||
cm_msg(MERROR,"splineo","ERROR %d opening calibration file %s",errno,
|
||||
filename);
|
||||
ret = SS_FILE_ERROR;
|
||||
}
|
||||
} else {
|
||||
|
||||
if (filename == NULL)
|
||||
cm_msg(MERROR,"splineo","NULL pointer to file name");
|
||||
else if (strlen(filename) <= 0)
|
||||
cm_msg(MERROR,"splineo","empty string supplied as file name");
|
||||
|
||||
if (npoints == NULL)
|
||||
cm_msg(MERROR,"splineo","NULL pointer to return number of data points");
|
||||
|
||||
if (X == NULL)
|
||||
cm_msg(MERROR,"splineo","NULL pointer to return X datavalues");
|
||||
|
||||
if (Y == NULL)
|
||||
cm_msg(MERROR,"splineo","NULL pointer to return Y data values");
|
||||
|
||||
ret = SS_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
#ifdef MIDEBUG1
|
||||
printf("<< splineo (%s)\n",filename);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
INT splinec(INT N, double *X, double *Y, double *s2, double *s3, double *dy,
|
||||
BOOL verbose) {
|
||||
/********************************************************************\
|
||||
|
||||
Routine: splinec
|
||||
A modified copy of F. Foroughi's Fortran 95 P_SPLINE routine
|
||||
|
||||
Purpose: calculate and return spline coefficients
|
||||
|
||||
Input:
|
||||
INT N number of data points
|
||||
double *X x data
|
||||
double *Y y data
|
||||
BOOL verbose show information on display if TRUE
|
||||
|
||||
Output:
|
||||
double *s2 interpolation coefficient
|
||||
double *s3 interpolation coefficient
|
||||
double *dy interpolation coefficient
|
||||
|
||||
Function value:
|
||||
INT SS_SUCCESS : Success
|
||||
FE_ERR_DRIVER
|
||||
|
||||
\********************************************************************/
|
||||
|
||||
INT ret;
|
||||
|
||||
#ifdef MIDEBUG1
|
||||
printf(">> splinec\n");
|
||||
#endif
|
||||
|
||||
#ifdef MIDEBUGD
|
||||
verbose = TRUE;
|
||||
#endif
|
||||
|
||||
ret = CM_SUCCESS;
|
||||
|
||||
if ((N > 2) &&(X != NULL) && (Y != NULL) && (s2 != NULL) && (s3 != NULL)&&
|
||||
(dy != NULL)) {
|
||||
|
||||
double *w;
|
||||
double *eta;
|
||||
double *h;
|
||||
double *g;
|
||||
double *c2;
|
||||
double *b;
|
||||
double *vv;
|
||||
INT i,n1,n2;
|
||||
BOOL conv;
|
||||
|
||||
n1 = N-1;
|
||||
n2 = n1-1;
|
||||
|
||||
#ifdef MIDEBUG2
|
||||
printf(" N = %d, n1 = %d, n2 = %d\n",N,n1,n2);
|
||||
#endif
|
||||
|
||||
/* allocate temporary arrays */
|
||||
w = (double *) calloc(N-2,sizeof(double));
|
||||
eta = (double *) calloc(N-2,sizeof(double));
|
||||
|
||||
h = (double *) calloc(N-1,sizeof(double));
|
||||
g = (double *) calloc(N-1,sizeof(double));
|
||||
c2 = (double *) calloc(N-1,sizeof(double));
|
||||
b = (double *) calloc(N-1,sizeof(double));
|
||||
vv = (double *) calloc(N-1,sizeof(double));
|
||||
|
||||
/* allocation OK? */
|
||||
if ((w!=NULL) && (eta!=NULL) && (h!=NULL) && (g!=NULL) && (c2!=NULL) &&
|
||||
(b!=NULL) && (vv!=NULL)) {
|
||||
|
||||
/* initialise variables */
|
||||
for (i=0;i<n1;i++) *(h+i) = *(X+i+1) - *(X+i);
|
||||
for (i=1,*g=0.0;i<n1;i++) *(g+i) = *(h+i-1) + *(h+i);
|
||||
for (i=1,*b=0.0;i<n1;i++) *(b+i) = 0.5* *(h+i-1)/ (*(g+i));
|
||||
for (i=0;i<n1;i++) *(dy+i) = (*(Y+i+1) - *(Y+i)) / (*(h+i));
|
||||
for (i=1,*vv=0.0;i<n1;i++) *(vv+i) = (*(dy+i) - *(dy+i-1))/ (*(g+i));
|
||||
for (i=1,*s2=0.0;i<n1;i++) *(s2+i) = 2*(*(vv+i));
|
||||
for (i=1,*c2=0.0;i<n1;i++) *(c2+i) = 3*(*(vv+i));
|
||||
|
||||
/* decompose until convergence of all */
|
||||
do {
|
||||
#ifdef MIDEBUG2
|
||||
printf("\n");
|
||||
#endif
|
||||
/* do calculation */
|
||||
for (i=0;i<n2;i++) {
|
||||
*(eta+i) = 0.0;
|
||||
*(w+i) = *(c2+i+1) - *(b+i+1) * *(s2+i);
|
||||
*(w+i) = (*(w+i)-(0.5 - *(b+i+1)) * *(s2+i+2) - *(s2+i+1))*SPLIN_OG;
|
||||
}
|
||||
|
||||
/* check for convergence */
|
||||
for (i=0,conv=TRUE;i<n2;i++) {
|
||||
#ifdef MIDEBUG2
|
||||
printf("w[%d] = %lf, eta[%d] = %lf\n",i+1,*(w+i),i+1,*(eta+i));
|
||||
#endif
|
||||
if (ABS(*(w+i)) > *(eta+i)) *(eta+i) = ABS(*(w+i));
|
||||
|
||||
if (*(eta+i)>SPLIN_EPSLN) {
|
||||
#ifdef MIDEBUG2
|
||||
printf("-> eta[%d] = %lf, s2[%d] = %lf, w[%d] = %lf\n",
|
||||
i+1,*(eta+i),i+2,*(s2+i+1),i+1,*(w+i));
|
||||
#endif
|
||||
*(s2+i+1) = *(s2+i+1) + *(w+i);
|
||||
conv = FALSE;
|
||||
}
|
||||
|
||||
}
|
||||
} while (!conv);
|
||||
|
||||
/* calculate s' */
|
||||
for (i=0;i<n1;i++)
|
||||
*(s3+i) = (*(s2+i+1)- *(s2+i)) / (*(h+i));
|
||||
|
||||
if (verbose) {
|
||||
for (i=0,printf("\n");i<n1;i++) {
|
||||
printf(" s2[%2.2d] = % lf, s3[%2.2d] = % lf, dy[%2.2d] = % lf\n",i+1,
|
||||
*(s2+i),i+1,*(s3+i),i+1,*(dy+i));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
cm_msg(MERROR,"splinec","ERROR allocating temporary arrays");
|
||||
ret = SS_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
/* free temporarily allocate data */
|
||||
if (w != NULL) free(w);
|
||||
if (eta != NULL) free(eta);
|
||||
if (h != NULL) free(h);
|
||||
if (g != NULL) free(g);
|
||||
if (c2 != NULL) free(c2);
|
||||
if (b != NULL) free(b);
|
||||
if (vv != NULL) free(vv);
|
||||
|
||||
} else {
|
||||
if (N <= 2)
|
||||
cm_msg(MERROR,"splinec","Not enough data points to calculate coefficients");
|
||||
|
||||
if (X == NULL)
|
||||
cm_msg(MERROR,"splinec","NULL pointer supplied as X data values");
|
||||
|
||||
if (Y == NULL)
|
||||
cm_msg(MERROR,"splinec","NULL pointer supplied as Y data values");
|
||||
|
||||
if (s2 == NULL)
|
||||
cm_msg(MERROR,"splinec","NULL pointer to return s2 spline coefficient");
|
||||
|
||||
if (s3 == NULL)
|
||||
cm_msg(MERROR,"splinec","NULL pointer to return s3 spline coefficient");
|
||||
|
||||
if (dy == NULL)
|
||||
cm_msg(MERROR,"splinec","NULL pointer to return dy spline coefficient");
|
||||
|
||||
ret = SS_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
#ifdef MIDEBUG1
|
||||
printf("<< splinec\n");
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------- */
|
||||
|
||||
INT splines(INT N, double *X, double *Y, double *s2, double *s3, double *dy,
|
||||
INT M, double *t, double *sp, BOOL verbose) {
|
||||
/********************************************************************\
|
||||
|
||||
Routine: splines
|
||||
A modified copy of F. Foroughi's Fortran 95 P_SPLINE routine
|
||||
|
||||
Purpose: perform cubic spline interpolations
|
||||
|
||||
Input:
|
||||
INT N number of data points
|
||||
double *X x data
|
||||
double *Y y data
|
||||
double *s2 interpolation coefficient
|
||||
double *s3 interpolation coefficient
|
||||
double *dy interpolation coefficient
|
||||
INT M number of points to be interpolated
|
||||
double *t values to be interpolated
|
||||
BOOL verbose show information on display if TRUE
|
||||
|
||||
Output:
|
||||
double *sp interpolated values
|
||||
|
||||
Function value:
|
||||
INT SS_SUCCESS : Success
|
||||
FE_ERR_DRIVER
|
||||
|
||||
\********************************************************************/
|
||||
|
||||
INT ret;
|
||||
INT i,j,i1,asc;
|
||||
double curx;
|
||||
double caly;
|
||||
|
||||
#ifdef MIDEBUG1
|
||||
printf(">> splines\n");
|
||||
#endif
|
||||
|
||||
#ifdef MIDEBUGD
|
||||
verbose = TRUE;
|
||||
#endif
|
||||
ret = CM_SUCCESS;
|
||||
|
||||
/* check parameter */
|
||||
if ((N>2) && (M>0) && (X!=NULL) && (Y!=NULL) && (s2 != NULL) &&
|
||||
(s3 != NULL) && (dy != NULL) && (t!=NULL) && (sp!=NULL)) {
|
||||
|
||||
if (*X < *(X+N-1))
|
||||
asc = 1; /* x values of calibration data are ascending */
|
||||
else
|
||||
asc = 0; /* x values of calibration data are descending */
|
||||
|
||||
/* for all values to interpolate */
|
||||
for(j=0;j<M;j++) {
|
||||
|
||||
curx = *(t+j);
|
||||
|
||||
/* value in interpolation range? */
|
||||
if ( ((curx >= *X) && (curx <= *(X+N-1)))||
|
||||
((curx <= *X) && (curx >= *(X+N-1))) ) {
|
||||
|
||||
/* ascending x values of calibration data? */
|
||||
if (asc) {
|
||||
|
||||
/* upper limit? */
|
||||
if (curx < *(X+N-1)) {
|
||||
|
||||
/* find interval of value */
|
||||
for (i=0,i1=-1;i<N;i++) {
|
||||
if (*(X+i) > curx) {
|
||||
i1 = i;
|
||||
break;
|
||||
}
|
||||
} /* for all values in the calibration table */
|
||||
|
||||
} else {
|
||||
/* for upper limit take last interval */
|
||||
i1 = N-1;
|
||||
}
|
||||
|
||||
/* descending x values of calibration data? */
|
||||
} else {
|
||||
/* lower limit? */
|
||||
if (curx > *(X+N-1)) {
|
||||
|
||||
/* find interval of value */
|
||||
for (i=0,i1=-1;i<N;i++) {
|
||||
if (*(X+i) < curx) {
|
||||
i1 = i;
|
||||
break;
|
||||
}
|
||||
} /* for all values in the calibration table */
|
||||
|
||||
} else {
|
||||
/* for lower limit take last interval */
|
||||
i1 = N-1;
|
||||
}
|
||||
}
|
||||
|
||||
/* interval found? */
|
||||
if (i1 != -1) {
|
||||
double ht1,ht2,prd,ss2,dq;
|
||||
|
||||
ht1 = curx - *(X+i1-1);
|
||||
ht2 = curx - *(X+i1);
|
||||
prd = ht1*ht2;
|
||||
ss2 = *(s2+i1-1) + ht1* *(s3+i1-1);
|
||||
dq = (*(s2+i1-1) + *(s2+i1)+ss2)*SPLIN_U6;
|
||||
caly = *(Y+i1-1) + ht1* *(dy+i1-1) + prd*dq;
|
||||
|
||||
} else {
|
||||
cm_msg(MERROR,"splines","Programming error? Interval for %lf not found",curx);
|
||||
ret = CM_SET_ERROR;
|
||||
}
|
||||
|
||||
} else {
|
||||
caly = SPLIN_INF;
|
||||
cm_msg(MERROR,"splines","Value %lf out of interpolation range (%lf %lf)",
|
||||
curx,*X,*(X+N-1));
|
||||
ret = CM_SET_ERROR;
|
||||
}
|
||||
|
||||
if (ret == CM_SUCCESS) {
|
||||
*(sp+j) = caly;
|
||||
if (verbose)
|
||||
printf("x[%d] = %lf -> y[%d] = %lf\n", j, curx, j, caly);
|
||||
}
|
||||
} /* for all values to be calculated */
|
||||
|
||||
} else {
|
||||
|
||||
/* check parameter */
|
||||
if (N <= 2)
|
||||
cm_msg(MERROR,"splines","Not enough data points");
|
||||
|
||||
if (X == NULL)
|
||||
cm_msg(MERROR,"splines","NULL pointer supplied as X data values");
|
||||
|
||||
if (Y == NULL)
|
||||
cm_msg(MERROR,"splines","NULL pointer supplied as Y data values");
|
||||
|
||||
if (s2 == NULL)
|
||||
cm_msg(MERROR,"splines","NULL pointer supplied as s2 spline coefficient");
|
||||
|
||||
if (s3 == NULL)
|
||||
cm_msg(MERROR,"splines","NULL pointer supplied as s3 spline coefficient");
|
||||
|
||||
if (dy == NULL)
|
||||
cm_msg(MERROR,"splines","NULL pointer supplied as dy spline coefficient");
|
||||
|
||||
if (M<=0)
|
||||
cm_msg(MERROR,"splines","Not enough data points");
|
||||
|
||||
if (t==NULL)
|
||||
cm_msg(MERROR,"splines","NULL pointer supplied as t data array");
|
||||
|
||||
if (sp==NULL)
|
||||
cm_msg(MERROR,"splines","NULL pointer to return interpolated values");
|
||||
|
||||
ret = SS_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
#ifdef MIDEBUG1
|
||||
printf("<< splines\n");
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
#ifdef SPLINE_MAIN
|
||||
|
||||
main () {
|
||||
|
||||
#ifdef CHECK4
|
||||
#define NCALS 4
|
||||
#else
|
||||
#define NCALS 5
|
||||
#endif
|
||||
|
||||
double x [NCALS];
|
||||
double y [NCALS];
|
||||
double s2[NCALS];
|
||||
double s3[NCALS];
|
||||
double dy[NCALS];
|
||||
double val[5], res[5];
|
||||
|
||||
x[0] = 0.0;
|
||||
x[1] = 1.0;
|
||||
x[2] = 2.0;
|
||||
x[3] = 3.0;
|
||||
#if (NCALS == 5)
|
||||
x[4] = 4.0;
|
||||
#endif
|
||||
|
||||
y[0] = 0.0;
|
||||
y[1] = 1.0;
|
||||
y[2] = 4.0;
|
||||
y[3] = 9.0;
|
||||
#if (NCALS == 5)
|
||||
y[4] = 16.0;
|
||||
#endif
|
||||
|
||||
/* calculate coefficients */
|
||||
splinec(sizeof(x)/sizeof(double),x,y,s2,s3,dy);
|
||||
|
||||
val[0] = 0.0;
|
||||
val[1] = 1.0;
|
||||
val[2] = 2.0;
|
||||
val[3] = 3.0;
|
||||
val[4] = 1.7;
|
||||
|
||||
/* perform cubic spline interpolation */
|
||||
splines(sizeof(x)/sizeof(double),x,y,s2,s3,dy,
|
||||
sizeof(val)/sizeof(double),val,res);
|
||||
|
||||
}
|
||||
#endif /* SPLINE_MAIN */
|
||||
|
||||
/* -------------------------------------------------------- EOF spline.c */
|
||||
@@ -0,0 +1,40 @@
|
||||
/********************************************************************\
|
||||
|
||||
Name: spline.h
|
||||
Created by: RA95
|
||||
|
||||
Contents: Header file to perform cubic spline interpolation
|
||||
|
||||
Revision 1.1 2017/01/26 07:37:25 raselli
|
||||
Original bulk muSR Midas 1.9.5 version
|
||||
|
||||
Revision 1.8 2016/09/09 13:14:40 raselli
|
||||
Bulk musr 09-SEP-2016
|
||||
|
||||
Revision 1.0 2003/09/29 12:18:57 midas
|
||||
|
||||
Date Name Modification
|
||||
-----------------------------------------------------------------
|
||||
25-SEP-2003 RA95 Initial version
|
||||
|
||||
\********************************************************************/
|
||||
|
||||
#ifndef _SPLINE_H_
|
||||
#define _SPLINE_H_
|
||||
|
||||
#define SPLIN_INF 1.0e36 /* infinite value */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include "midas.h"
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
INT splineo(char *, INT *, double **, double **, BOOL);
|
||||
INT splinec(INT, double *, double *, double *, double *, double *, BOOL);
|
||||
INT splines(INT, double *, double *, double *, double *, double *,
|
||||
INT, double *, double *, BOOL);
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
#endif /* #ifndef _SPLINE_H */
|
||||
@@ -0,0 +1,123 @@
|
||||
/*******************************************************************\
|
||||
|
||||
Name: expmag_fe.cxx
|
||||
Created by: Stefan Mathis
|
||||
Contents: Slow Control Frontend for beamline magnets
|
||||
|
||||
\********************************************************************/
|
||||
|
||||
#include "midas.h"
|
||||
|
||||
#include "mfe.h"
|
||||
|
||||
#include "bus/tcpip.h"
|
||||
#include "class/generic.h"
|
||||
|
||||
#include "device/expmag.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Global Variables Required by mfe.h
|
||||
******************************************************************************/
|
||||
|
||||
//! The frontend name (client name) as seen by other MIDAS clients
|
||||
const char *frontend_name = "Experiment magnet";
|
||||
|
||||
//! The frontend file name, don't change it
|
||||
const char *frontend_file_name = __FILE__;
|
||||
|
||||
//! frontend_loop is called periodically if this variable is TRUE
|
||||
BOOL frontend_call_loop = TRUE;
|
||||
|
||||
//! a frontend status page is displayed with this frequency in ms
|
||||
INT display_period = 1000;
|
||||
|
||||
//! maximum event size produced by this frontend
|
||||
INT max_event_size = 10000;
|
||||
|
||||
//! maximum event size for fragmented events (EQ_FRAGMENTED)
|
||||
INT max_event_size_frag = 5 * 1024 * 1024;
|
||||
|
||||
//! buffer size to hold events
|
||||
INT event_buffer_size = 10 * 10000;
|
||||
|
||||
/*******************************************************************************
|
||||
* Equipment List Required by mfe.h
|
||||
******************************************************************************/
|
||||
|
||||
DEVICE_DRIVER expmag_driver[] = {
|
||||
// { name, *dd, channels, *bd, flags }
|
||||
{"expmag", expmag, 9, NULL, DF_INPUT},
|
||||
};
|
||||
|
||||
/*!
|
||||
* equipment_common_overwrite:
|
||||
*
|
||||
* - If that flag is TRUE, then the contents of the "equipment" structure is
|
||||
* copied to the ODB on each start of the front-end.
|
||||
*
|
||||
* - If the flag is FALSE, then the ODB values are kept on the start of the
|
||||
* front-end
|
||||
*/
|
||||
BOOL equipment_common_overwrite = FALSE;
|
||||
|
||||
/*******************************************************************************
|
||||
* Equipment Structure Required by mfe.h
|
||||
******************************************************************************/
|
||||
|
||||
EQUIPMENT equipment[] = {
|
||||
{
|
||||
"expmag", /* equipment name */
|
||||
{
|
||||
16, /* Event ID associated with equipm. */
|
||||
0, /* Trigger mask */
|
||||
"SYSTEM", /* Event buffer to send events into */
|
||||
EQ_SLOW, /* equipment type */
|
||||
0, /* Event source (LAM/IRQ) */
|
||||
"FIXED", /* Data format to produce */
|
||||
TRUE, /* Enable flag */
|
||||
RO_RUNNING |
|
||||
RO_TRANSITIONS, /* Combination of Read-On flags RO_xxx */
|
||||
60000, /* Readout interval/Polling time in ms */
|
||||
0, /* Stop run when limit is reached */
|
||||
0, /* Number of events in super event */
|
||||
1, /* log history every event */
|
||||
"", /* Host on which FE is running */
|
||||
"", /* Frontend name */
|
||||
"" /* Source file used for user FE */
|
||||
},
|
||||
cd_gen_read, /* readout routine */
|
||||
cd_gen, /* class driver main routine */
|
||||
expmag_driver, /* device driver list */
|
||||
NULL, /* init string */
|
||||
},
|
||||
{""}};
|
||||
|
||||
/*******************************************************************************
|
||||
* Routines Required by mfe.h
|
||||
*
|
||||
* Can be overwritten to modify the default frontend behaviour.
|
||||
******************************************************************************/
|
||||
|
||||
INT poll_event(INT source, INT count, BOOL test) { return CM_SUCCESS; };
|
||||
|
||||
INT interrupt_configure(INT cmd, INT source, POINTER_T adr) {
|
||||
return CM_SUCCESS;
|
||||
};
|
||||
|
||||
INT frontend_init() {
|
||||
return CM_SUCCESS;
|
||||
}
|
||||
|
||||
INT frontend_loop() {
|
||||
return CM_SUCCESS;
|
||||
}
|
||||
|
||||
INT frontend_exit() { return CM_SUCCESS; }
|
||||
|
||||
INT begin_of_run(INT run_number, char *error) { return CM_SUCCESS; }
|
||||
|
||||
INT pause_run(INT run_number, char *error) { return CM_SUCCESS; }
|
||||
|
||||
INT resume_run(INT run_number, char *error) { return CM_SUCCESS; }
|
||||
|
||||
INT end_of_run(INT run_number, char *error) { return CM_SUCCESS; }
|
||||
Submodule
+1
Submodule midas_lan_gpib added at adba88295e
Reference in New Issue
Block a user