#include #include #include #include #ifdef __ppc #include #include #else #define sky_memcpy memcpy #endif #include "pcs_common.h" #include "rtcdef.h" #include "ppccApSem.h" #include "pclinkdef.h" /*********************************************************************** * rtc_outdat.c -- * * Write data to pclink ... * * History: * 30-Mar-2005 CLN Use IDX_RWM1 for P13 commands in a2 and ncvt2 * 14-Oct-2004 TRG Use ctrlWord defs from pclinkdef.h, preparatory * to supporting SPAs. * 15-Apr-2004 TRG GET_SYSTEMTIMING: to get acq+pcs+psrtc timing, set * this param to 1 in acq/acq_bolt.c and here. * 04-Dec-2003 TRG Separate function and struct defs for FPDP-PCLIM. * 21-Nov-2003 TRG outdat: check nfaultFlag (not nfcount) for faults * indicated by "faultbit". Note that "faultbit" is * set also to indicate SOP-EOP transition. * 28-Jul-2003 TRG Convert from doublePrecision to singlePrecision. * 23-Apr-2001 TRG Specify "short" in struct defs w0struct, w1struct. * 20-Dec-2000 TRG Added HA/PSA for new PS1AU(-) and PS1AL(-). * 11-Jan-1999 TRG Merged fortran and C routines for greater efficiency. * 08-Jan-1999 TRG rewrite pclwords_ for greater speed. * 07-Jan-1999 TRG expect angle in radians: 2.88rad = 165deg * 25-Sep-1998 BD made this version to be called from FORTRAN * 17-Sep-1998 BD added inputs for Convert and Block-bypass bits * 14-Sep-1998 BD Max angle, ie. all bits on, per Bob Marsala, is 165. * 08-Sep-1998 BD Create (as pclwords.c). * ************************************************************************/ #ifndef GET_SYSTEMTIMING #define GET_SYSTEMTIMING 0 /* ONE to send psrtc time to acq */ #endif /*======================================================== * Externals ... *=======================================================*/ extern float nstxTime; extern struct nstx_pcs_collect_integer nstx_pcs_collect_integer; extern struct nstx_pcs_collect_real nstx_pcs_collect_real; extern struct nstx_pcs_gen nstx_pcs_gen; extern struct pcs_common_ftn pcs_common_ftn; extern struct pubData *pub; /* Defined in rtc_indat.c */ extern void wrvmebuf_(); /* write to pclink card on VME */ /*========================================================= * Structures and definitions ... *========================================================*/ struct psInfo { /* definitions for houseAddr and psAddr */ unsigned short houseAddr; unsigned short psAddr; int nlink; /* PC Link number (for FPDP-PCLIM only) */ float *data; /* addr of firingAngle a1[] or a2[] */ int *ncvt; /* addr of ncvt1[] or ncvt2[] */ int icoil; /* idx into data[] and ncvt[] */ }; /*------------------------------------------------- * Indexes into coil arrays a1,a2,ncvt,nbb *------------------------------------------------*/ #define A1 nstx_pcs_collect_real.a1 #define A2 nstx_pcs_collect_real.a2 #define NCVT1 nstx_pcs_collect_integer.ncvt1 #define NCVT2 nstx_pcs_collect_integer.ncvt2 #define NBB nstx_pcs_collect_integer.nbb static struct psInfo psInfo[] = { 8,1,LINK4,A1,NCVT1,IDX_RWM1 /* SPA 8.1 */ , 8,2,LINK4,A1,NCVT1,IDX_RWM2 /* SPA 8.2 */ , 8,3,LINK4,A1,NCVT1,IDX_RWM3 /* SPA 8.3 */ ,59,7,LINK0,A1,NCVT1,IDX_OH /* OH(+) */ ,61,7,LINK0,A2,NCVT2,IDX_OH /* " (-) */ ,33,3,LINK3,A1,NCVT1,IDX_PF4 /* PF4 */ ,33,4,LINK3,A2,NCVT2,IDX_RWM1 /* P13 SPA DC Source */ ,34,3,LINK2,A1,NCVT1,IDX_PF1aU /* PF1a Upper(+) */ ,18,3,LINK1,A2,NCVT2,IDX_PF1aU /* " " (-) */ ,34,1,LINK2,A1,NCVT1,IDX_PF1aL /* PF1a Lower(+) */ ,34,4,LINK2,A2,NCVT2,IDX_PF1aL /* " " (-) */ ,34,2,LINK2,A1,NCVT1,IDX_PF1b /* PF1b */ ,19,1,LINK2,A1,NCVT1,IDX_PF2U /* PF2 Upper */ ,18,1,LINK1,A1,NCVT1,IDX_PF2L /* PF2 Lower */ ,17,2,LINK1,A1,NCVT1,IDX_PF3U /* PF3 Upper(+) */ ,33,1,LINK3,A2,NCVT2,IDX_PF3U /* " " (-) */ ,18,2,LINK1,A1,NCVT1,IDX_PF3L /* PF3 Lower(+) */ ,33,2,LINK3,A2,NCVT2,IDX_PF3L /* " " (-) */ ,19,2,LINK2,A1,NCVT1,IDX_PF5 /* PF5 */ ,17,1,LINK1,A1,NCVT1,IDX_CHI /* CHI */ ,62,7,LINK0,A1,NCVT1,IDX_TF /* TF */ }; #define NUM_PWRSUPPLIES (sizeof(psInfo)/sizeof(psInfo[0])) /* ********************************************************************* */ #if USE_FPDP_FOR_PCLINK /********************************************************** * reverseAllBits: * FPDP-PCLIM hardware was set up with all ctrlWord bits * "backwards" from the software's impression! * This function allows us to reverse the bits ... **********************************************************/ static int reverseAllBits( int src ) /* FPDP-PCLIM only */ { int i,ibit; union {unsigned int ival; unsigned char bval[4];} in,out; static unsigned char reverse[256]; if (!reverse[1]) { //initialize "reverse[]" array for (i=0 ; i<256 ; i++) { for (ibit=0 ; ibit<8 ; ibit++) { if (i & (1<houseAddr; /* house address ... */ cw->haddress = k; for (parity=1 ; k ; k>>=1) { parity ^= (k & 1); } cw->haparity = parity; k = p->psAddr; /* power supply address ... */ cw->psaddress = k; for (parity=1 ; k ; k>>=1) { parity ^= (k & 1); } cw->psparity = parity; cw->nlink = p->nlink; /* fcpc link number */ } nwords = sizeof(ctrlWords)/sizeof(short); } /*------------------------------------------------------ * Copy template to ctrlWords[]. This must be done * because we reverse all the bits within ctrlWords[] * before sending it to FPDP-PCLIM, so we need * a fresh copy each time ... *-----------------------------------------------------*/ sky_memcpy(ctrlWords,ctrlWordsTemplate,sizeof(ctrlWords)); /*------------------------------------------------------ * Set "faultbit" if there has been a fault or * if we have just completed the shot. *-----------------------------------------------------*/ msgFlag = 0; errCnt = 0; if (nstx_pcs_gen.nfaultFlag) { /*================ fault =============*/ if (!faultbitVal) { faultbitVal = 1; msgFlag = 1; for (ipwr=0 ; ipwricoil; /* idx into coil arrays */ cw = ctrlWords + ipwr; if (p->nlink < LINK4) { /* writing data to PCLIM ... */ cwp = (void *)cw; cwp->blkbypass = NBB[icoil]; cwp->convert = p->ncvt[icoil]; k = (int)((p->data[icoil] / 2.88 )*255. + 0.5); /* divide rads by 2.88, or degrees by 165 */ cwp->fangle = k; } else { /* writing data to SPAIM ... */ cws = (void *)cw; cws->convert = p->ncvt[icoil]; //k = ((int)(p->data[icoil] + .5)) & 0X0800; //must be b/t -2048 and +2047 if (p->data[icoil] > 0) { k = (int) (p->data[icoil] * (2047./10.)); } else { k = (int) (p->data[icoil] * (2048./10.)); } cws->data = k; } /* Set data parity for ctrlWord *-------------------------------------*/ k = cw->devData; /* 14-bit devData segment */ for (parity=1 ; k ; k>>=1) { parity ^= (k & 1); } cw->dataparity = parity; if (cw->nlink != p->nlink) { pcsmsg(0,"t=%.3f ipwr=%-2d ctrlWord nlink=%d not %d", nstxTime,ipwr,cw->nlink,p->nlink); errCnt++; } } if (errCnt) errorExit("Exiting due to 'nlink' errors: errCnt=%d",errCnt); /*------------------------------------------- * Reverse all bits in each ctrlWord to match * PCLIM bit configuration ... *------------------------------------------*/ for (ipwr=0 ; ipwru.pubTime[pub->u.pubIdx]; setApSem(&cpuNSTX.acq,SEMIDX_NOTIFY,&udata,0); } #endif /* __ppc */ } return; } #else /* else, not USE_FPDP_FOR_PCLINK */ ///struct w0struct { /// unsigned short haddress:6; /// unsigned short haparity:1; /* parity for house address */ /// unsigned short psaddress:3; /// unsigned short psparity:1; /* parity for ps address */ /// unsigned short nothing:3; /// unsigned short faultbit:1; /// unsigned short stearingbit:1; /// }; ///struct w1struct { /// unsigned short spare:3; /// unsigned short blkbypass:1; /// unsigned short unused:1; /// unsigned short convert:1; /// unsigned short fangle:8; /// unsigned short parity:1; /* parity for top 14 bits */ /// unsigned short stearingbit:1; /// }; ///union u0 { /// struct w0struct s; /// unsigned short word0int; /// }; ///union u1 { /// struct w1struct s; /// unsigned short word1int; /// }; /***************************************************************** * outdat_: *****************************************************************/ void outdat_() /* VME-based PCLIM */ { int k; int msgFlag; int icoil; int ipwr; int parity; struct psInfo *p; union u0 *u0; union u1 *u1; static int faultbitVal; static int firsttime = 1; static int nsopeopB4; static struct buf { union u0 u0; union u1 u1; } buf[NUM_PWRSUPPLIES]; static int nwords = NUM_PWRSUPPLIES*2; /*--------------------------------------------------------------- * C Includes and Common: * C ------------------- * C NCVT1 - Convert bit for alpha 1 * C NBB - circuit block bypassed * INTEGER*4 ncvt1(NCOILS), ncvt2(NCOILS), nbb(NCOILS) * REAL*8 a1(NCOILS), a2(NCOILS) *--------------------------------------------------------------*/ /*--------------------------------------------------------- * Word 0: * First time only: fill in houseAddr and psAddr * Set fault bit each time through. *--------------------------------------------------------*/ if (firsttime) { firsttime = 0; for (ipwr=0,p=psInfo ; ipwrword0int = 0; /* initialize to zero */ k = p->houseAddr; /* house address ... */ u0->s.haddress = k; for (parity=1 ; k ; k>>=1) { parity ^= (k & 1); } u0->s.haparity = parity; k = p->psAddr; /* power supply address ... */ u0->s.psaddress = k; for (parity=1 ; k ; k>>=1) { parity ^= (k & 1); } u0->s.psparity = parity; } } /*------------------------------------------------------ * Set word0 "faultbit" if there has been a fault or * if we have just completed the shot. *-----------------------------------------------------*/ msgFlag = 0; if (nstx_pcs_gen.nfaultFlag) { /*================ fault =============*/ if (!faultbitVal) { faultbitVal = 1; msgFlag = 1; for (ipwr=0 ; ipwricoil; /* idx into coil arrays */ u1 = &buf[ipwr].u1; u1->word1int = 0; /* initialize to zero */ u1->s.blkbypass = NBB[icoil]; u1->s.convert = p->ncvt[icoil]; k = (int)((p->data[icoil] / 2.88 )*255. + 0.5); /* divide rads by 2.88, or degrees by 165 */ u1->s.fangle = k; /*----------------------------------------------- * Parity in w1 is for entire word, excluding * the steering bit ... *----------------------------------------------*/ k = u1->word1int >> 2; for (parity=1 ; k ; k>>=1) { parity ^= (k & 1); } u1->s.parity = parity; u1->s.stearingbit = 1; } wrvmebuf_(buf,&nwords); if (msgFlag) { /// float t = nstx_pcs_gen.ntdata*FAST_DT + nstx_pcs_gen.tsop; /// pcsmsg(0,"outdat: *FAULT* nerracq=%d t=%.3f", /// nstx_pcs_collect_integer.nerracq,t); } /// { ///#ifdef __ppc /// static long long btB4,btNow; /// if (!btB4) /// { /// ppc_readtimer(&btB4); /// } /// ppc_readtimer(&btNow); /// nstx_pcs_collect_real.dummy1 = BT2SEC(btNow-btB4); /// btB4 = btNow; ///#endif /* __ppc */ /// } return; } #endif /* not USE_FPDP_FOR_PCLINK */