/* * cagft() * * ca get field test * * test ca get over the range of CA data types */ static int cagft(char *pname) { const unsigned maxTries = 1000ul; unsigned ntries = 0u; chid chan_id; int status; int i; /* * convert name to chan id */ status = ca_search(pname, &chan_id); SEVCHK(status,NULL); status = ca_pend_io(5.0); if(status != ECA_NORMAL){ SEVCHK(ca_clear_channel(chan_id),NULL); printf("Not Found %s\n", pname); return -1; } printf("name:\t%s\n", ca_name(chan_id)); printf("native type:\t%s\n", dbr_type_to_text(ca_field_type(chan_id))); printf("native count:\t%lu\n", ca_element_count(chan_id)); /* * fetch as each type */ for(i=0; i<=LAST_BUFFER_TYPE; i++){ if(ca_field_type(chan_id)==DBR_STRING) { if( (i!=DBR_STRING) && (i!=DBR_STS_STRING) && (i!=DBR_TIME_STRING) && (i!=DBR_GR_STRING) && (i!=DBR_CTRL_STRING)) { continue; } } /* ignore write only types */ if ( i == DBR_PUT_ACKT || i == DBR_PUT_ACKS ) { continue; } status = ca_array_get_callback( i, ca_element_count(chan_id), chan_id, printit, NULL); SEVCHK(status, NULL); outstanding++; } /* * wait for the operation to complete * before returning */ while ( ntries < maxTries ) { unsigned long oldOut; oldOut = outstanding; ca_pend_event ( 0.05 ); if ( ! outstanding ) { SEVCHK ( ca_clear_channel ( chan_id ), NULL ); printf ( "\n\n" ); return 0; } if ( outstanding == oldOut ) { ntries++; } } SEVCHK ( ca_clear_channel ( chan_id ), NULL ); return -1; }
void SearchTag() { int i = 0; //MAXI2_GAUGE(Dual Gauge) for(i=0;i<2;i++) { ca_search(VacTagData2[i], &VacTagDatachid2[i]); istatus = ca_pend_io(0.1); printf("Maxi2 %d : %d\n", i, istatus); } //TMP3~4 for(i=0;i<2;i++) { ca_search(TmpStsTagData[i], &TmpStsTagDatachid[i]); istatus = ca_pend_io(0.1); printf("TmpSts %d : %d\n", i, istatus); ca_search(TmpAmpTagData[i], &TmpAmpTagDatachid[i]); istatus = ca_pend_io(0.1); printf("TmpAmp %d : %d\n", i, istatus); ca_search(TmpRpmTagData[i], &TmpRpmTagDatachid[i]); istatus = ca_pend_io(0.1); printf("TmpRpm %d : %d\n", i, istatus); ca_search(TmpTempTagData[i], &TmpTempTagDatachid[i]); istatus = ca_pend_io(0.1); printf("TmpTemp %d : %d\n", i, istatus); } }
static int CACommand(string strcmd) { #if 0 //In event callback function, It' dosen't work ca_get() function. I don't understand the reason. struct dbr_time_long shotdata; chid shot_id; ca_create_channel("CCS_SHOT_NUMBER",NULL, NULL,20,&shot_id); ca_pend_io(1.0); int state = ca_state(shot_id); printf("State:%d\n", state); ca_get(DBR_TIME_LONG, shot_id, (void *)&shotdata); int status = ca_pend_io(1.0); if(status != ECA_NORMAL) { fprintf(stdout, "SHOT number: %s denied access\n",ca_name(shot_id)); return; }; fprintf(stdout, "%s:%d\n",ca_name(shot_id),shotdata.value); #else FILE *fp= popen (strcmd.c_str(), "r"); char buf[20]; while (fgets (buf, sizeof(buf), fp) ) {}; pclose(fp); return ((strcmd.compare("ShotNum")== 0)?atoi(buf):0); #endif }
void ECCD_Calorimetric::slot_SET_DATA(void) { chid searchID; int istatus; int iDATA = 1; ca_search ("EC1_WCS_SET_DATA", &searchID); istatus = ca_pend_io(0.1); ca_put(DBR_INT, searchID, &iDATA); istatus = ca_pend_io(0.1); }
int main(int argc,char **argv) { int indval,field; SEVCHK(ca_task_initialize(),"ca_task_initialize"); SEVCHK(ca_search("enumCputDTYP",&putCchid[0]),"ca_search failure"); SEVCHK(ca_search("enumCputPRIO",&putCchid[1]),"ca_search failure"); SEVCHK(ca_search("enumCputVAL" ,&putCchid[2]),"ca_search failure"); SEVCHK(ca_search("enumMDbputDTYP",&putMDbchid[0]),"ca_search failure"); SEVCHK(ca_search("enumMDbputPRIO",&putMDbchid[1]),"ca_search failure"); SEVCHK(ca_search("enumMDbputVAL" ,&putMDbchid[2]),"ca_search failure"); SEVCHK(ca_search("enumMCaputDTYP",&putMCachid[0]),"ca_search failure"); SEVCHK(ca_search("enumMCaputPRIO",&putMCachid[1]),"ca_search failure"); SEVCHK(ca_search("enumMCaputVAL" ,&putMCachid[2]),"ca_search failure"); SEVCHK(ca_search("enumCmbbi.DTYP" ,&getCchid[0]),"ca_search failure"); SEVCHK(ca_search("enumCmbbi.PRIO" ,&getCchid[1]),"ca_search failure"); SEVCHK(ca_search("enumCmbbi.VAL" ,&getCchid[2]),"ca_search failure"); SEVCHK(ca_search("enumMDbmbbi.DTYP" ,&getMDbchid[0]),"ca_search failure"); SEVCHK(ca_search("enumMDbmbbi.PRIO" ,&getMDbchid[1]),"ca_search failure"); SEVCHK(ca_search("enumMDbmbbi.VAL" ,&getMDbchid[2]),"ca_search failure"); SEVCHK(ca_search("enumMCambbi.DTYP" ,&getMCachid[0]),"ca_search failure"); SEVCHK(ca_search("enumMCambbi.PRIO" ,&getMCachid[1]),"ca_search failure"); SEVCHK(ca_search("enumMCambbi.VAL" ,&getMCachid[2]),"ca_search failure"); SEVCHK(ca_pend_io(5.0),"ca_pend_io failure"); for(indval=0; indval<2; indval++) { SEVCHK(ca_put(DBR_STRING,putCchid[0],dtypValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putCchid[1],prioValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putCchid[2],valValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putMDbchid[0],dtypValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putMDbchid[1],prioValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putMDbchid[2],valValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putMCachid[0],dtypValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putMCachid[1],prioValue[indval]),"ca_put"); SEVCHK(ca_put(DBR_STRING,putMCachid[2],valValue[indval]),"ca_put"); /*Wait until evertthing updated*/ ca_pend_event(2.0); for(field=0; field<3; field++) { SEVCHK(ca_get(DBR_STRING,getCchid[field],&getCvalue[field]), "ca_get"); SEVCHK(ca_get(DBR_STRING,getMDbchid[field],&getMDbvalue[field]), "ca_get"); SEVCHK(ca_get(DBR_STRING,getMCachid[field],&getMCavalue[field]), "ca_get"); } SEVCHK(ca_pend_io(5.0),"ca_pend_io failure"); printReport(indval); } return(0); }
int readtag(cUINT utype, chid searchID) { cUINT type; switch(utype) { case T_CIP_INT: type = DBR_INT; ca_get(type, searchID, &iDATA); break; case T_CIP_DINT: type = DBR_DOUBLE; ca_get(type, searchID, &dblDATA); break; case T_CIP_REAL: type = DBR_FLOAT; ca_get(type, searchID, &fltDATA); break; case T_CIP_BITS: type = T_CIP_DINT; ca_get(type, searchID, &fltDATA); break; } istatus = ca_pend_io(0.1); if(istatus != 1) return 0; return 1; }
int main(int argc,char **argv) { int status; double value=1.0; double newvalue=0.0; char *pvname; double blockTime; if(argc!=3) { printf("usage: testsyncgroup <pvname> <blockTime>\n"); exit(1); } pvname = argv[1]; sscanf(argv[2],"%le",&blockTime); SEVCHK(ca_task_initialize(),"ca_task_initialize"); SEVCHK(ca_search(pvname,&mychid),"ca_search_and_connect"); SEVCHK(ca_pend_io(1.0),"ca_pend_io"); SEVCHK(ca_sg_create(&gid),"ca_sg_create"); SEVCHK(ca_sg_array_put(gid,DBR_DOUBLE,1,mychid,(void *)&value), "ca_sg_array_put"); SEVCHK(ca_sg_array_get(gid,DBR_DOUBLE,1,mychid,(void *)&newvalue), "ca_sg_array_put"); status = ca_sg_block(gid,blockTime); printf("ca_sg_block status=%s\n",ca_message(status)); status = ca_sg_test(gid); printf("ca_sg_test status=%s\n",ca_message(status)); printf("newvalue=%f\n",newvalue); return(0); }
void writetag(cUINT utype, chid searchID) { cUINT type; switch (utype) { case T_CIP_INT: type = DBR_INT; ca_put(type, searchID, &iWriteDATA); break; case T_CIP_DINT: type = DBR_DOUBLE; ca_put(type, searchID, &dblWriteDATA); break; case T_CIP_BITS: type = DBR_INT; if (bDATA%2==0) bDATA=0; else bDATA=255; ca_put(type, searchID, &bWriteDATA); break; case T_CIP_REAL: type = DBR_FLOAT; ca_put(type, searchID, &fltWriteDATA); break; }//end switch istatus = ca_pend_io(0.1); //printf("WRITEtag istatus : %d\n", istatus); }
// extern "C" int epicsShareAPI ca_pend ( ca_real timeout, int early ) { if ( early ) { return ca_pend_io ( timeout ); } else { return ca_pend_event ( timeout ); } }
int connect_pvs (pv* pvs, int nPvs) { int returncode = create_pvs ( pvs, nPvs, 0); if ( returncode == 0 ) { /* Wait for channels to connect */ int result = ca_pend_io (caTimeout); if (result == ECA_TIMEOUT) { if (nPvs > 1) { fprintf(stderr, "Channel connect timed out: some PV(s) not found.\n"); } else { fprintf(stderr, "Channel connect timed out: '%s' not found.\n", pvs[0].name); } returncode = 1; } } return returncode; }
int main(int argc,char **argv) { chid mychid; unsigned short value; if(argc!=3) { printf("usage: caputackt pvname value\n"); exit(1); } sscanf(argv[2],"%hu",&value); SEVCHK(ca_task_initialize(),"ca_task_initialize"); SEVCHK(ca_search(argv[1],&mychid), "ca_search"); ca_pend_io(5.0); SEVCHK(ca_put(DBR_PUT_ACKT,mychid,&value),"ca_put"); ca_pend_event(1.0); /* ca_task_exit(); */ return(0); }
int main(int argc,char **argv) { int status; double value=1.0; char *pvname; double pendEventTime; int maxTrys = 3; if(argc!=3) { printf("usage: testputnotify <pvname> <pendEventTime>\n"); exit(1); } pvname = argv[1]; sscanf(argv[2],"%le",&pendEventTime); SEVCHK(ca_task_initialize(),"ca_task_initialize"); SEVCHK(ca_search(pvname,&mychid),"ca_search_and_connect"); SEVCHK(ca_pend_io(1.0),"ca_pend_io"); while(TRUE) { SEVCHK(ca_array_put_callback(DBR_DOUBLE,1,mychid, (void *)&value,putCallback,NULL), "ca_put_callback"); ntrys=0; gotCallback=FALSE; while(!gotCallback && ntrys <=maxTrys) { status = ca_pend_event(pendEventTime); if(status!=ECA_NORMAL && status!=ECA_TIMEOUT) printf("ca_pend_event status=%s\n",ca_message(status)); ntrys++; if(ntrys==maxTrys) { printf(" Never got callback\n"); break; } } printf(" number ca_pend_event = %d\n",ntrys); } return(0); }
void popupPvInfo(DisplayInfo *displayInfo) { DlElement *pE; Record **records; chid chId; int i, status; Record *pR; Channel *pCh; char descName[MAX_TOKEN_LENGTH]; char *pDot; double connTimeout; #if DEBUG_PVINFO XUngrabPointer(display,CurrentTime); #endif /* Check if another call is in progress */ if(pvInfo) { medmPostMsg(1,"popupPvInfo: " "Another PV Info request is already in progress\n" " It is probably having problems\n" " Wait for it to finish\n"); return; } /* Create the dialog box if it has not been created */ if(!pvInfoS) createPvInfoDlg(); /* Get the records */ records = getPvInfoFromDisplay(displayInfo, &nPvInfoPvs, &pE); if(!records) return; pvInfoElement = pE; /* Allocate space */ pvInfo = (PvInfo *)calloc(nPvInfoPvs, sizeof(PvInfo)); if(!pvInfo) { medmPostMsg(1,"popupPvInfo: Memory allocation error\n"); if(records) free(records); if(pvInfoS && XtIsManaged(pvInfoS)) return; } /* Loop over the records, initialize, and initiate search for DESC */ for(i=0; i < nPvInfoPvs; i++) { /* Initialize */ pvInfo[i].pvChid = NULL; pvInfo[i].pvOk = False; pvInfo[i].timeOk = False; pvInfo[i].descChid = NULL; pvInfo[i].descOk = False; strcpy(pvInfo[i].descVal, NOT_AVAILABLE); #if defined(DBR_CLASS_NAME) && DO_RTYP pvInfo[i].rtypOk = False; strcpy(pvInfo[i].rtypVal, NOT_AVAILABLE); #endif /* Check for a valid record */ if(records[i]) { pR = pvInfo[i].record = records[i]; pCh = getChannelFromRecord(pR); if(!pCh) continue; if(!pCh->chid) continue; chId = pvInfo[i].pvChid = pCh->chid; } else continue; pvInfo[i].pvOk = True; /* Don't try the others unless the PV is connected */ if(ca_state(chId) != cs_conn || !ca_read_access(chId)) continue; /* Construct the DESC name */ strcpy(descName,ca_name(chId)); pDot = strchr(descName,'.'); if(pDot) { /* Assume it is a name with a field and replace the field * with DESC */ strcpy(pDot,".DESC"); } else { /* Append .DESC */ strcat(descName,".DESC"); } /* Search for the DESC */ status = ca_search(descName, &pvInfo[i].descChid); if(status == ECA_NORMAL) { pvInfo[i].descOk = True; } else { medmPostMsg(1,"popupPvInfo: DESC: ca_search for %s: %s\n", descName, ca_message(status)); } } /* Free the records, they are now stored in pvInfo */ if(records) free(records); /* Wait for the searches (Timeouts should be uncommon) */ status=ca_pend_io(CA_PEND_IO_TIME); if(status != ECA_NORMAL) { medmPostMsg(1,"popupPvInfo: Waited %g seconds. " "Did not find the DESC information (%s).\n", CA_PEND_IO_TIME, descName); } /* Loop over the records and do the gets */ nPvInfoCbs = 0; for(i=0; i < nPvInfoPvs; i++) { if(!pvInfo[i].pvOk) continue; /* Don't try the others unless the PV is connected */ chId = pvInfo[i].pvChid; if(ca_state(chId) != cs_conn || !ca_read_access(chId)) continue; /* Get the DESC */ if(ca_state(pvInfo[i].descChid) == cs_conn && ca_read_access(pvInfo[i].descChid)) { /* Do the get */ status = ca_get_callback(DBR_STRING, pvInfo[i].descChid, pvInfoDescGetCb, &pvInfo[i]); if(status == ECA_NORMAL) { nPvInfoCbs++; } else { pvInfo[i].descOk = False; medmPostMsg(1,"pvInfoConnectCb: DESC: ca_array_get_callback" " for %s: %s\n", ca_name(pvInfo[i].descChid), ca_message(status)); } } else { pvInfo[i].descOk = False; } /* Get the time value as a string */ status = ca_get_callback(DBR_TIME_STRING, chId, pvInfoTimeGetCb, &pvInfo[i]); if(status == ECA_NORMAL) { nPvInfoCbs++; } else { medmPostMsg(1,"popupPvInfo: STAMP: ca_get_callback for %s: %s\n", ca_name(chId), ca_message(status)); } #if defined(DBR_CLASS_NAME) && DO_RTYP /* Get the RTYP */ status = ca_get_callback(DBR_CLASS_NAME, chId, pvInfoRtypGetCb, &pvInfo[i]); if(status == ECA_NORMAL) { nPvInfoCbs++; } else { medmPostMsg(1,"popupPvInfo: RTYP: ca_get_callback for %s: %s\n", ca_name(chId), ca_message(status)); } #endif } /* Add a timeout and poll if there are callbacks * The timeout is a safety net and should never be called * All callbacks should come back inside the EPICS_CA_CONN_TMO * Wait for 2 times this */ if(nPvInfoCbs) { ca_poll(); /* May not be really necessary here */ status = envGetDoubleConfigParam(&EPICS_CA_CONN_TMO, &connTimeout); if (status == 0) pvInfoTime = (unsigned long)(2000.*connTimeout+.5); else pvInfoTime = PVINFO_TIMEOUT; pvInfoTimeoutId = XtAppAddTimeOut(appContext, pvInfoTime, pvInfoTimeout, NULL); pvInfoTimerOn = True; } else { pvInfoWriteInfo(); } #if DEBUG_PVINFO print("popupPvInfo: nPvInfoCbs=%d timeout=%ld\n", nPvInfoCbs, nPvInfoCbs?pvInfoTime:0L); #endif }
/* * capft * * test ca_put() over a range of data types * */ static int capft( char *pname, char *pvalue ) { dbr_short_t shortvalue; dbr_long_t longvalue; dbr_float_t floatvalue; dbr_char_t charvalue; dbr_double_t doublevalue; unsigned long ntries = 10ul; int status; chid chan_id; if (((*pname < ' ') || (*pname > 'z')) || ((*pvalue < ' ') || (*pvalue > 'z'))){ printf("\nusage \"pv name\",\"value\"\n"); return -1; } /* * convert name to chan id */ status = ca_search(pname, &chan_id); SEVCHK(status,NULL); status = ca_pend_io(5.0); if(status != ECA_NORMAL){ SEVCHK(ca_clear_channel(chan_id),NULL); printf("Not Found %s\n", pname); return -1; } printf("name:\t%s\n", ca_name(chan_id)); printf("native type:\t%d\n", ca_field_type(chan_id)); printf("native count:\t%lu\n", ca_element_count(chan_id)); /* * string value ca_put */ status = ca_put( DBR_STRING, chan_id, pvalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_STRING); if(ca_field_type(chan_id)==0)goto skip_rest; if(sscanf(pvalue,"%hd",&shortvalue)==1) { /* * short integer ca_put */ status = ca_put( DBR_SHORT, chan_id, &shortvalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_SHORT); status = ca_put( DBR_ENUM, chan_id, &shortvalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_ENUM); charvalue=(dbr_char_t)shortvalue; status = ca_put( DBR_CHAR, chan_id, &charvalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_CHAR); } if(sscanf(pvalue,"%d",&longvalue)==1) { /* * long integer ca_put */ status = ca_put( DBR_LONG, chan_id, &longvalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_LONG); } if(epicsScanFloat(pvalue, &floatvalue)==1) { /* * single precision float ca_put */ status = ca_put( DBR_FLOAT, chan_id, &floatvalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_FLOAT); } if(epicsScanDouble(pvalue, &doublevalue)==1) { /* * double precision float ca_put */ status = ca_put( DBR_DOUBLE, chan_id, &doublevalue); SEVCHK(status, NULL); verify_value(chan_id, DBR_DOUBLE); } skip_rest: /* * wait for the operation to complete * (outstabnding decrements to zero) */ while(ntries){ ca_pend_event(1.0); if(!outstanding){ SEVCHK(ca_clear_channel(chan_id),NULL); printf("\n\n"); return 0; } ntries--; } SEVCHK(ca_clear_channel(chan_id),NULL); return -1; }
int cagetFuZE(char *pvName, char *pvValue) { RequestT request = get; OutputT format = plain; chtype dbrType = -1; unsigned long reqElems = 0; int n, result; pv* pvs; int i; unsigned long nElems; result = ca_context_create(ca_disable_preemptive_callback); pvs = calloc(1, sizeof(pv)); pvs[0].name = pvName; connect_pvs(pvs, 1); for (n = 0; n < 1; n++) { /* Set up pvs structure */ /* -------------------- */ /* Get natural type and array count */ nElems = ca_element_count(pvs[n].chid); pvs[n].dbfType = ca_field_type(pvs[n].chid); pvs[n].dbrType = dbrType; /* Set up value structures */ if (format != specifiedDbr) { pvs[n].dbrType = dbf_type_to_DBR_TIME(pvs[n].dbfType); /* Use native type */ if (dbr_type_is_ENUM(pvs[n].dbrType)) /* Enums honour -n option */ { if (enumAsNr) pvs[n].dbrType = DBR_TIME_INT; else pvs[n].dbrType = DBR_TIME_STRING; } else if (floatAsString && (dbr_type_is_FLOAT(pvs[n].dbrType) || dbr_type_is_DOUBLE(pvs[n].dbrType))) { pvs[n].dbrType = DBR_TIME_STRING; } } /* Issue CA request */ /* ---------------- */ if (ca_state(pvs[n].chid) == cs_conn) { nConn++; pvs[n].onceConnected = 1; if (request == callback) { /* Event handler will allocate value and set nElems */ pvs[n].reqElems = reqElems > nElems ? nElems : reqElems; result = ca_array_get_callback(pvs[n].dbrType, pvs[n].reqElems, pvs[n].chid, event_handler, (void*)&pvs[n]); } else { /* We allocate value structure and set nElems */ pvs[n].nElems = reqElems && reqElems < nElems ? reqElems : nElems; pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].nElems)); if (!pvs[n].value) { fprintf(stderr,"Memory allocation failed\n"); return -1; } result = ca_array_get(pvs[n].dbrType, pvs[n].nElems, pvs[n].chid, pvs[n].value); } pvs[n].status = result; } else { pvs[n].status = ECA_DISCONN; } } if (!nConn) return -1; /* No connection? We're done. */ /* Wait for completion */ /* ------------------- */ result = ca_pend_io(caTimeout); if (result == ECA_TIMEOUT) { fprintf(stderr, "Read operation timed out: some PV data was not read.\n"); return -1; } if (request == callback) /* Also wait for callbacks */ { if (caTimeout != 0) { double slice = caTimeout / PEND_EVENT_SLICES; for (n = 0; n < PEND_EVENT_SLICES; n++) { ca_pend_event(slice); if (nRead >= nConn) break; } if (nRead < nConn) { fprintf(stderr, "Read operation timed out: some PV data was not read.\n"); return -1; } } else { /* For 0 timeout keep waiting until all are done */ while (nRead < nConn) { ca_pend_event(1.0); } } } // Does this kill the connection?? ca_context_destroy(); sprintf(pvValue, "%s\n", val2str(pvs[0].value, pvs[0].dbrType, 0)); return 1; }
void mexFunction( int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[]) { int i,j, k, status,buflen,Cnt, Hndl, L,M,N, NumHandles, commandswitch; int *HndlArray; mxArray *mymxArray; double *myDblPr; chtype RequestType; char PVName[PV_NAME_LENGTH_MAX+1]; // char MCAMessageString[MCA_MESSAGE_STRING_LENGTH_MAX+1]; dbr_string_t StrBuffer; const char *MCAInfoFields[]={"PVName","ElementCount","NativeType","State","MCAMessage","Host"}; char *NativeTypeStrings[] = {"STRING","INT","FLOAT","ENUM","CHAR","LONG","DOUBLE"}; if(!CA_INITIALIZED) // Initialize CA if not initialized (first call) { mexPrintf("Initializing MATLAB Channel Access ... \n"); status = ca_task_initialize(); if(status!=ECA_NORMAL) mexErrMsgTxt("Unable to initialise Challel Access\n"); CA_INITIALIZED = true; // Register a function to be called when a this mex-file is cleared from memory // with 'clear' or when exitting MATLAB mexAtExit(mca_cleanup); // Lock the mex-file so that it can not be cleared without explicitly // mexUnclock mexLock(); //start periodic polling: /* PollTimerHandle = SetTimer(NULL,NULL,MCA_POLL_PERIOD,background_poll); if(PollTimerHandle) mexPrintf("Periodic CA polling started! System Timer ID: %u\n",PollTimerHandle); else mexWarnMsgTxt("Failed to start periodic CA polling\n"); */ } commandswitch = (int)mxGetScalar(prhs[0]); switch(commandswitch) { case 0: mexUnlock(); break; case 1: // MCAOPEN - add channel(s) by PV names, all arguments following prhs[0] // must be strings - names of PV's for(i=1;i<nrhs;i++) { mxGetString(prhs[i],PVName,PV_NAME_LENGTH_MAX+1); status = ca_search(PVName,&(CHNLS[HandlesUsed].CHID)); if(status == ECA_NORMAL) // if not - go on to the next PV name { status = ca_pend_io(MCA_SEARCH_TIMEOUT); if (status == ECA_NORMAL) { // Allocate persistent memory for the DataBuffer on this channel // to hold all elements of the DBR_XXX type // nearest to the native type // RequestType = dbf_type_to_DBR(ca_field_type(CHNLS[HandlesUsed].CHID)); // Cnt=ca_element_count(CHNLS[HandlesUsed].CHID); CHNLS[HandlesUsed].NumElements = ca_element_count(CHNLS[HandlesUsed].CHID); CHNLS[HandlesUsed].NativeType2DBR = dbf_type_to_DBR(ca_field_type(CHNLS[HandlesUsed].CHID)); CHNLS[HandlesUsed].MonitorEventCount = 0; switch(CHNLS[HandlesUsed].NativeType2DBR) { case DBR_STRING: CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_string_t)); break; case DBR_INT: // As defined in db_access.h DBR_INT = DBR_SHORT = 1 CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_short_t)); break; case DBR_FLOAT: CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_float_t)); break; case DBR_ENUM: CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_enum_t)); break; case DBR_CHAR: CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_char_t)); break; case DBR_LONG: CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_short_t)); break; case DBR_DOUBLE: CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_double_t)); break; } mexMakeMemoryPersistent(CHNLS[HandlesUsed].DataBuffer); if(CHNLS[HandlesUsed].NativeType2DBR==DBR_STRING) // CACHE { if(CHNLS[HandlesUsed].NumElements==1) // Create MATLAB string - originally empty CHNLS[HandlesUsed].CACHE = mxCreateString(""); else // Create MATLAB cell array of strings { CHNLS[HandlesUsed].CACHE = mxCreateCellMatrix(1,CHNLS[HandlesUsed].NumElements); for(k=0;k<CHNLS[HandlesUsed].NumElements;k++) { mymxArray = mxCreateString(""); mexMakeArrayPersistent(mymxArray); mxSetCell(CHNLS[HandlesUsed].CACHE, k, mymxArray); } } } else // Make CACHE a numeric mxArray { CHNLS[HandlesUsed].CACHE = mxCreateDoubleMatrix(1,CHNLS[HandlesUsed].NumElements,mxREAL); } mexMakeArrayPersistent(CHNLS[HandlesUsed].CACHE); plhs[i-1]=mxCreateScalarDouble(++HandlesUsed); } else plhs[i-1]=mxCreateScalarDouble(0); } else plhs[i-1]=mxCreateScalarDouble(0); } break; case 2:// MCAOPEN - add channel(s) by PV names. The arguments following prhs[0] // argument must be a cell array of strings - PV names L = mxGetM(prhs[1])*mxGetN(prhs[1]); plhs[0] = mxCreateDoubleMatrix(1,L,mxREAL); myDblPr = mxGetPr(plhs[0]); for(i=0;i<L;i++) { mymxArray = mxGetCell(prhs[1],i); mxGetString(mymxArray,PVName,PV_NAME_LENGTH_MAX+1); status = ca_search(PVName,&(CHNLS[HandlesUsed].CHID)); if(status == ECA_NORMAL) // if not - go on to the next PV name { status = ca_pend_io(MCA_IO_TIMEOUT); if (status == ECA_NORMAL) { // Allcate persistent memory for the DataBuffer on this channel //RequestType = dbf_type_to_DBR(ca_field_type(CHNLS[HandlesUsed].CHID)); CHNLS[HandlesUsed].NativeType2DBR = dbf_type_to_DBR(ca_field_type(CHNLS[HandlesUsed].CHID)); CHNLS[HandlesUsed].NumElements = ca_element_count(CHNLS[HandlesUsed].CHID); CHNLS[HandlesUsed].MonitorEventCount = 0; //Cnt=ca_element_count(CHNLS[HandlesUsed].CHID); switch(CHNLS[HandlesUsed].NativeType2DBR) { case DBR_STRING: CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_string_t)); break; case DBR_INT: // As defined in db_access.h DBR_INT = DBR_SHORT = 1 CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_short_t)); break; case DBR_FLOAT: CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_float_t)); break; case DBR_ENUM: CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_enum_t)); break; case DBR_CHAR: CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_char_t)); break; case DBR_LONG: CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_short_t)); break; case DBR_DOUBLE: CHNLS[HandlesUsed].DataBuffer = mxCalloc(CHNLS[HandlesUsed].NumElements,sizeof(dbr_double_t)); break; } mexMakeMemoryPersistent(CHNLS[HandlesUsed].DataBuffer); if(CHNLS[HandlesUsed].NativeType2DBR == DBR_STRING) // CACHE { CHNLS[HandlesUsed].CACHE = mxCreateCellMatrix(1,CHNLS[HandlesUsed].NumElements); for(k=0;k<CHNLS[HandlesUsed].NumElements;k++) { mymxArray = mxCreateString(StrBuffer); mexMakeArrayPersistent(mymxArray); mxSetCell(CHNLS[HandlesUsed].CACHE, k, mymxArray); } } else { CHNLS[HandlesUsed].CACHE = mxCreateDoubleMatrix(1,CHNLS[HandlesUsed].NumElements,mxREAL); } mexMakeArrayPersistent(CHNLS[HandlesUsed].CACHE); myDblPr[i] = ++HandlesUsed; } else myDblPr[i] = 0; } else myDblPr[i] = 0; } break; case 3: // MCAOPEN Return names of connected channels as cell array of strings plhs[0] = mxCreateCellArray(1, &HandlesUsed); for(i=0;i<HandlesUsed;i++) { if(CHNLS[i].CHID!=NULL) { mymxArray = mxCreateString(ca_name(CHNLS[i].CHID)); mxSetCell(plhs[0], i, mymxArray); } else { mymxArray = mxCreateString(""); //mexPrintf("Handle: %d PV: %s\n",i+1, "Cleared Channel"); mxSetCell(plhs[0], i, mymxArray); } } break; case 5: // MCACLOSE permanently clear channel Hndl = (int)mxGetScalar(prhs[1]); if(Hndl<1 || Hndl>HandlesUsed) mexErrMsgTxt("Handle out of range"); // If a monitor is installed, set the EVID pointer to NULL // ca_clear_event dos not do it by itself if(CHNLS[Hndl-1].EVID) CHNLS[Hndl-1].EVID = NULL; // If there is Callback String - destroy it if(CHNLS[Hndl-1].MonitorCBString) { mxFree(CHNLS[Hndl-1].MonitorCBString); CHNLS[Hndl-1].MonitorCBString =NULL; } if(ca_state(CHNLS[Hndl-1].CHID)==3) mexWarnMsgTxt("Channel previously cleared"); else if(ca_clear_channel(CHNLS[Hndl-1].CHID)!=ECA_NORMAL) mexErrMsgTxt("ca_clear_channel failed"); break; case 10: // MCAINFO return channels info as MATLAB structure array if(HandlesUsed>0) { plhs[0] = mxCreateStructMatrix(1,HandlesUsed,6,MCAInfoFields); for(i=0;i<HandlesUsed;i++) { mxSetFieldByNumber(plhs[0],i,0,mxCreateString(ca_name(CHNLS[i].CHID))); mxSetFieldByNumber(plhs[0],i,1,mxCreateScalarDouble(ca_element_count(CHNLS[i].CHID))); mxSetFieldByNumber(plhs[0],i,5,mxCreateString(ca_host_name(CHNLS[i].CHID))); switch(ca_state(CHNLS[i].CHID)) { case 1: // Disconnected due to Server or Network - may reconnect mxSetFieldByNumber(plhs[0],i,2,mxCreateString("unknown")); mxSetFieldByNumber(plhs[0],i,3,mxCreateString("disconnected")); mxSetFieldByNumber(plhs[0],i,4,mxCreateString("Disconnected due to server or network problem")); break; case 2: // Normal connection mxSetFieldByNumber(plhs[0],i,2,mxCreateString(NativeTypeStrings[ca_field_type(CHNLS[i].CHID)])); mxSetFieldByNumber(plhs[0],i,3,mxCreateString("connected")); mxSetFieldByNumber(plhs[0],i,4,mxCreateString("Normal connection")); break; case 3: // Disconnected by user mxSetFieldByNumber(plhs[0],i,2,mxCreateString("unknown")); mxSetFieldByNumber(plhs[0],i,3,mxCreateString("disconnected")); mxSetFieldByNumber(plhs[0],i,4,mxCreateString("Permanently disconnected (cleared) by the user")); break; } } } else { mexWarnMsgTxt("No connected PV's found"); plhs[0] = mxCreateDoubleMatrix(0,0,mxREAL); } break; case 11: // MCAINFO return info for 1 channel by handle number Hndl = (int)mxGetScalar(prhs[1]); if(Hndl<1 || Hndl>HandlesUsed) mexErrMsgTxt("Handle out of range"); plhs[0] = mxCreateStructMatrix(1,1,6,MCAInfoFields); mxSetFieldByNumber(plhs[0],0,0,mxCreateString(ca_name(CHNLS[Hndl-1].CHID))); mxSetFieldByNumber(plhs[0],0,1,mxCreateScalarDouble(ca_element_count(CHNLS[Hndl-1].CHID))); mxSetFieldByNumber(plhs[0],0,5,mxCreateString(ca_host_name(CHNLS[Hndl-1].CHID))); switch(ca_state(CHNLS[Hndl-1].CHID)) { case 1: // Disconnected due to Server or Network - may reconnect mxSetFieldByNumber(plhs[0],0,2,mxCreateString("unknown")); mxSetFieldByNumber(plhs[0],0,3,mxCreateString("disconnected")); mxSetFieldByNumber(plhs[0],0,4,mxCreateString("Disconnected due to server or network problem")); break; case 2: // Normal connection mxSetFieldByNumber(plhs[0],0,2,mxCreateString(NativeTypeStrings[ca_field_type(CHNLS[Hndl-1].CHID)])); mxSetFieldByNumber(plhs[0],0,3,mxCreateString("connected")); mxSetFieldByNumber(plhs[0],0,4,mxCreateString("Normal connection")); break; case 3: // Disconnected by user mxSetFieldByNumber(plhs[0],0,2,mxCreateString("unknown")); mxSetFieldByNumber(plhs[0],0,3,mxCreateString("disconnected")); mxSetFieldByNumber(plhs[0],0,4,mxCreateString("Permanently disconnected (cleared) by the user")); break; }; break; case 12: // MCASTATE return an array of status (1 - OK, 0 - disconnected or cleared) if(HandlesUsed>0) { plhs[0] = mxCreateDoubleMatrix(1,HandlesUsed,mxREAL); myDblPr = mxGetPr(plhs[0]); for(i=0;i<HandlesUsed;i++) myDblPr[i] = (double)(ca_state(CHNLS[i].CHID)==2); } else { mexWarnMsgTxt("No connected PV's found"); plhs[0] = mxCreateDoubleMatrix(0,0,mxREAL); } break; case 30: // poll ca_poll(); break; case 50: // MCAGET Get PV values by their MCA handles for(i=0;i<nrhs-1;i++) // First loop: place all ca_get requests in the buffer { Hndl = (int)mxGetScalar(prhs[1+i]); //start from[1]: [0] argument is the commnads switch if(Hndl<1 || Hndl>HandlesUsed) mexErrMsgTxt("Invalid Handle"); RequestType = dbf_type_to_DBR(ca_field_type(CHNLS[Hndl-1].CHID)); Cnt = ca_element_count(CHNLS[Hndl-1].CHID); status = ca_array_get(RequestType,Cnt,CHNLS[Hndl-1].CHID,CHNLS[Hndl-1].DataBuffer); if(status!=ECA_NORMAL) mexPrintf("Error in call to ca_array_get\n"); } status = ca_pend_io(MCA_GET_TIMEOUT); if(status!=ECA_NORMAL) mexErrMsgTxt("... ca_pend_io call timed out \n"); for(i=0;i<nrhs-1;i++) // Another loop to copy data from temp structures to MATLAB { Hndl = (int)mxGetScalar(prhs[1+i]); RequestType = RequestType = dbf_type_to_DBR(ca_field_type(CHNLS[Hndl-1].CHID)); Cnt = ca_element_count(CHNLS[Hndl-1].CHID); if(RequestType==DBR_STRING) { if(Cnt==1) plhs[i] = mxCreateString((char*)(*((dbr_string_t*)(CHNLS[Hndl-1].DataBuffer)))); else { plhs[i] = mxCreateCellMatrix(1,Cnt); for(j=0;j<Cnt;j++) mxSetCell(plhs[i], j, mxCreateString((char*)(*((dbr_string_t*)(CHNLS[Hndl-1].DataBuffer)+j)))); } } else { plhs[i] = mxCreateDoubleMatrix(1,Cnt,mxREAL); myDblPr = mxGetPr(plhs[i]); switch(dbf_type_to_DBR(ca_field_type(CHNLS[Hndl-1].CHID))) { case DBR_INT: // As defined in db_access.h DBR_INT = DBR_SHORT = 1 for(j=0;j<Cnt;j++) myDblPr[j]= (double)(*((dbr_short_t*)(CHNLS[Hndl-1].DataBuffer)+j)); break; case DBR_FLOAT: for(j=0;j<Cnt;j++) myDblPr[j]= (double)(*((dbr_float_t*)(CHNLS[Hndl-1].DataBuffer)+j)); break; case DBR_ENUM: for(j=0;j<Cnt;j++) myDblPr[j]= (double)(*((dbr_enum_t*)(CHNLS[Hndl-1].DataBuffer)+j)); break; case DBR_CHAR: for(j=0;j<Cnt;j++) myDblPr[j]= (double)(*((dbr_char_t*)(CHNLS[Hndl-1].DataBuffer)+j)); break; case DBR_LONG: for(j=0;j<Cnt;j++) myDblPr[j]= (double)(*((dbr_long_t*)(CHNLS[Hndl-1].DataBuffer)+j)); break; case DBR_DOUBLE: for(j=0;j<Cnt;j++) myDblPr[j]= (double)(*((dbr_double_t*)(CHNLS[Hndl-1].DataBuffer)+j)); break; } } } break; case 51: // MCAGET Get scalar PV of the same type // second argument is an array of handles // returns an array of values myDblPr = mxGetPr(prhs[1]); M = mxGetM(prhs[1]); N = mxGetN(prhs[1]); NumHandles = M*N; plhs[0] = mxCreateDoubleMatrix(M,N,mxREAL); for(i=0;i<NumHandles;i++) // First loop: place all ca_get requests in the buffer { Hndl = (int)myDblPr[i]; if(Hndl<1 || Hndl>HandlesUsed) mexErrMsgTxt("Invalid Handle"); RequestType = dbf_type_to_DBR(ca_field_type(CHNLS[Hndl-1].CHID)); status = ca_array_get(DBR_DOUBLE,1,CHNLS[Hndl-1].CHID,mxGetPr(plhs[0])+i); if(status!=ECA_NORMAL) mexPrintf("Error in call to ca_array_get\n"); } status = ca_pend_io(MCA_GET_TIMEOUT); if(status!=ECA_NORMAL) mexErrMsgTxt("... ca_pend_io call timed out \n"); break; case 70: // MCAPUT NumHandles = (nrhs-1)/2; for(i=0;i<NumHandles;i++) { j = 2+i*2; Hndl = (int)mxGetScalar(prhs[1+i*2]); if(Hndl<1 || Hndl>HandlesUsed) mexErrMsgTxt("Handle out of range - no values written"); // Set the status to 0 - mcaput_callback will write 1, if successful CHNLS[Hndl-1].LastPutStatus = 0; RequestType = dbf_type_to_DBR(ca_field_type(CHNLS[Hndl-1].CHID)); Cnt = ca_element_count(CHNLS[Hndl-1].CHID); // If a value to write is passed as a string - the number of elements to write // is 1 , NOT the length of the string returned by mxGetNumberOfElements if(mxIsChar(prhs[j])) L=1; else L = min(mxGetNumberOfElements(prhs[j]),Cnt); // Copy double or string data from MATLAB prhs[] to DataBuffer // on each channel if(RequestType==DBR_STRING) { // STRING type is is passed as a cell array of strings // A a 1-row MATLAB character array (1 string) may also be passed as a value if(mxIsChar(prhs[j])) { mxGetString(prhs[j], StrBuffer, sizeof(dbr_string_t)); strcpy((char*)(*((dbr_string_t*)(CHNLS[Hndl-1].DataBuffer))),StrBuffer); } else if(mxIsCell(prhs[j])) { for(k=0;k<L;k++) { mxGetString(mxGetCell(prhs[j],k), StrBuffer, sizeof(dbr_string_t)); strcpy((char*)(*((dbr_string_t*)(CHNLS[Hndl-1].DataBuffer)+k)),StrBuffer); } } } else { myDblPr = mxGetPr(prhs[j]); switch(RequestType) { case DBR_INT: // As defined in db_access.h DBR_INT = DBR_SHORT = 1 for(k=0;k<L;k++) *((dbr_short_t*)(CHNLS[Hndl-1].DataBuffer)+k) = (dbr_short_t)(myDblPr[k]); break; case DBR_FLOAT: for(k=0;k<L;k++) *((dbr_float_t*)(CHNLS[Hndl-1].DataBuffer)+k) = (dbr_float_t)(myDblPr[k]); break; case DBR_ENUM: for(k=0;k<L;k++) *((dbr_enum_t*)(CHNLS[Hndl-1].DataBuffer)+k) = (dbr_enum_t)(myDblPr[k]); break; case DBR_CHAR: for(k=0;k<L;k++) *((dbr_char_t*)(CHNLS[Hndl-1].DataBuffer)+k) = (dbr_char_t)(myDblPr[k]); break; case DBR_LONG: for(k=0;k<L;k++) *((dbr_long_t*)(CHNLS[Hndl-1].DataBuffer)+k) = (dbr_long_t)(myDblPr[k]); break; case DBR_DOUBLE: for(k=0;k<L;k++) *((dbr_double_t*)(CHNLS[Hndl-1].DataBuffer)+k) = (dbr_double_t)(myDblPr[k]); break; } } // place request in the que status = ca_array_put_callback(RequestType,L,CHNLS[Hndl-1].CHID,CHNLS[Hndl-1].DataBuffer, mcaput_callback,&(CHNLS[Hndl-1].LastPutStatus)); if(status!=ECA_NORMAL) mexPrintf("ca_array_put_callback failed\n"); } status = ca_pend_event(MCA_PUT_TIMEOUT); plhs[0]=mxCreateDoubleMatrix(1,NumHandles,mxREAL); myDblPr = mxGetPr(plhs[0]); for(i=0;i<NumHandles;i++) { Hndl = (int)mxGetScalar(prhs[1+i*2]); myDblPr[i] = (double)CHNLS[Hndl-1].LastPutStatus; } break; case 80: // MCAPUT - fast unconfirmed put for scalar numeric PV's myDblPr = mxGetPr(prhs[1]); M = mxGetM(prhs[1]); N = mxGetN(prhs[1]); NumHandles = M*N; plhs[0] = mxCreateDoubleMatrix(M,N,mxREAL); myDblPr = mxGetPr(plhs[0]); for(i=0;i<NumHandles;i++) { myDblPr = mxGetPr(plhs[0]); Hndl = (int)(*(mxGetPr(prhs[1])+i)); if(Hndl<1 || Hndl>HandlesUsed) mexErrMsgTxt("Handle out of range - no values written"); status = ca_array_put(DBR_DOUBLE,1,CHNLS[Hndl-1].CHID,mxGetPr(prhs[2])+i); if(status!=ECA_NORMAL) { myDblPr[i] = 0; //mexPrintf("ca_array_put_callback failed\n"); } else { myDblPr[i] = 1; } } status = ca_pend_io(MCA_PUT_TIMEOUT); break; case 100: // MCAMON install Monitor or replace MonitorCBString Hndl = (int)mxGetScalar(prhs[1]); // Check if the handle is within range if(Hndl<1 || Hndl>HandlesUsed) { plhs[0]=mxCreateScalarDouble(0); mexErrMsgTxt("Invalid Handle"); } if(CHNLS[Hndl-1].EVID) // if VID is not NULL - another monitor is already installed - replace MonitorCBString { if(CHNLS[Hndl-1].MonitorCBString) // Free memory for occupied by the old MonitorCBString { mxFree(CHNLS[Hndl-1].MonitorCBString); CHNLS[Hndl-1].MonitorCBString = NULL; } if(nrhs>2) // Check if the new string is specified { if(mxIsChar(prhs[2])) { buflen = mxGetM(prhs[2])*mxGetN(prhs[2])+1; CHNLS[Hndl-1].MonitorCBString = (char *)mxMalloc(buflen); mexMakeMemoryPersistent(CHNLS[Hndl-1].MonitorCBString); mxGetString(prhs[2],CHNLS[Hndl-1].MonitorCBString,buflen); } else mexErrMsgTxt("Third argument must be a string\n"); } plhs[0]=mxCreateScalarDouble(1); } else // No monitor is presently installed; { RequestType = dbf_type_to_DBR(ca_field_type(CHNLS[Hndl-1].CHID)); // Closest to the native if(nrhs>2) { if(mxIsChar(prhs[2])) { buflen = mxGetM(prhs[2])*mxGetN(prhs[2])+1; CHNLS[Hndl-1].MonitorCBString = (char *)mxMalloc(buflen); mexMakeMemoryPersistent(CHNLS[Hndl-1].MonitorCBString); mxGetString(prhs[2],CHNLS[Hndl-1].MonitorCBString,buflen); } else mexErrMsgTxt("Third argument must be a string\n"); } else CHNLS[Hndl-1].MonitorCBString = NULL; // Set MonitorCBString to NULL so that mcaMonitorEventHandler only copies data to CACHE // Count argument set to 0 - native count status = ca_add_array_event(RequestType,0,CHNLS[Hndl-1].CHID, mcaMonitorEventHandler, &CHNLS[Hndl-1], 0.0, 0.0, 0.0, &(CHNLS[Hndl-1].EVID)); if(status!=ECA_NORMAL) { mexPrintf("ca_add_array_event failed\n"); plhs[0]=mxCreateScalarDouble(0); } else { ca_poll(); plhs[0]=mxCreateScalarDouble(1); } } break; case 200: // Clear Monitor MCACLEARMON Hndl = (int)mxGetScalar(prhs[1]); if(Hndl<1 || Hndl>HandlesUsed) mexErrMsgTxt("Invalid Handle"); if(!CHNLS[Hndl-1].EVID) mexErrMsgTxt("No monitor installed - can not clear"); status = ca_clear_event(CHNLS[Hndl-1].EVID); if(status!=ECA_NORMAL) mexPrintf("ca_clear_event failed\n"); // Set the EVID pointer to NULL (ca_clear_event dos not do it by itself) // to use as a FLAG that no monitors are installed CHNLS[Hndl-1].EVID = NULL; // Reset CHNLS[Hndl-1].MonitorEventCount = 0; // If there is Callback String - destroy it if(CHNLS[Hndl-1].MonitorCBString) { mxFree(CHNLS[Hndl-1].MonitorCBString); CHNLS[Hndl-1].MonitorCBString =NULL; } break; case 300: // MCACACHE Get Cached values of a monitored PV for(i=0;i<nrhs-1;i++) { Hndl = (int)mxGetScalar(prhs[1+i]); // if(Hndl<1 || Hndl>HandlesUsed || !CHNLS[Hndl-1].CACHE) if(Hndl<1 || Hndl>HandlesUsed) plhs[i] = mxCreateDoubleMatrix(0,0,mxREAL); else { plhs[i] = mxDuplicateArray(CHNLS[Hndl-1].CACHE); CHNLS[Hndl-1].MonitorEventCount = 0; } } break; case 500: // MCAMON Info on installed monitors L = 0; HndlArray = (int*)mxCalloc(HandlesUsed,sizeof(int)); for(i=0;i<HandlesUsed;i++) // Count installed monitors { if(CHNLS[i].EVID) HndlArray[L++]=i+1; } if(L>0) { plhs[0] = mxCreateDoubleMatrix(1,L,mxREAL); myDblPr = mxGetPr(plhs[0]); plhs[1] = mxCreateCellMatrix(1,L); for(i=0;i<L;i++) { myDblPr[i] = (double)HndlArray[i]; mxSetCell(plhs[1],i,mxCreateString(CHNLS[HndlArray[i]-1].MonitorCBString)); } } else { plhs[0] = mxCreateDoubleMatrix(0,0,mxREAL); plhs[1] = mxCreateCellMatrix(0,0); } break; case 510: // MCAMONEVENTS Event count fot monitors plhs[0] = mxCreateDoubleMatrix(1,HandlesUsed,mxREAL); myDblPr = mxGetPr(plhs[0]); for(i=0;i<HandlesUsed;i++) myDblPr[i]=(double)(CHNLS[i].MonitorEventCount); break; case 1000: // print timeout settings plhs[0] = mxCreateDoubleMatrix(3,1,mxREAL); mexPrintf("MCA timeout settings\n:"); mexPrintf("mcaopen\t%f [s]\n", MCA_SEARCH_TIMEOUT ); mexPrintf("mcaget\t%f [s]\n", MCA_GET_TIMEOUT ); mexPrintf("mcaput\t%f [s]\n", MCA_PUT_TIMEOUT ); myDblPr = mxGetPr(plhs[0]); myDblPr[0] = MCA_SEARCH_TIMEOUT; myDblPr[1] = MCA_GET_TIMEOUT; myDblPr[2] = MCA_PUT_TIMEOUT; break; case 1001: // set MCA_SEARCH_TIMEOUT // return delay value MCA_SEARCH_TIMEOUT = mxGetScalar(prhs[1]); plhs[0] = mxCreateScalarDouble(MCA_SEARCH_TIMEOUT); break; case 1002: // set MCA_GET_TIMEOUT // return delay value MCA_GET_TIMEOUT = mxGetScalar(prhs[1]); plhs[0] = mxCreateScalarDouble(MCA_GET_TIMEOUT); break; case 1003: // set MCA_PUT_TIMEOUT // return delay value MCA_PUT_TIMEOUT = mxGetScalar(prhs[1]); plhs[0] = mxCreateScalarDouble(MCA_PUT_TIMEOUT); break; } }
int main(int argc,char **argv) { char *pval; double sleepSecs = 0.0; int clearEvery = 0; int indValue = 1; int indNumberCallback = 1; while((argc>1) && (argv[1][0] == '-')) { int i; char option; int narg; option = toupper((argv[1])[1]); pval = argv[2]; argc -= 1; narg = 1; if(option=='S') { sscanf(pval,"%lf",&sleepSecs); argc -= 1; ++narg; } else if(option=='C') { sscanf(pval,"%d",&clearEvery); argc -= 1; ++narg; } else if(option=='V') { verbose = 1; } else { usageExit(); } for(i=1; i<argc; i++) argv[i] = argv[i + narg]; } if(argc != 4) usageExit(); pvname = argv[1]; pvalue1 = argv[2]; pvalue2 = argv[3]; pevent = epicsEventCreate(epicsEventEmpty); SEVCHK(ca_context_create(ca_enable_preemptive_callback), "ca_task_initialize"); while(1) { SEVCHK(ca_search(pvname,&mychid),"ca_search_and_connect"); if(ca_pend_io(3.0)!=ECA_NORMAL) { epicsThreadSleep(5.0); continue; } while(1) { epicsEventWaitStatus status; if(indValue==0) { indValue = 1; pvalue = pvalue2; } else { indValue = 0; pvalue=pvalue1; } if(++indNumberCallback >= MAXnumberCallback) indNumberCallback=0; numberCallback[indNumberCallback] = ++expectedCallback; status = ca_array_put_callback(DBR_STRING,1,mychid, pvalue,putCallback,&numberCallback[indNumberCallback]); if(status!=ECA_NORMAL) { printf("ca_array_put_callback %s\n",ca_message(status)); epicsThreadSleep(2.0); continue; } if((clearEvery>0) && ((expectedCallback % clearEvery)==0)) { ca_flush_io(); epicsThreadSleep(sleepSecs); SEVCHK(ca_clear_channel(mychid),"ca_clear_channel"); ca_flush_io(); expectedCallback = 0; epicsThreadSleep(sleepSecs); if(verbose) { printTime(); printf("Issued ca_clear_channel expectedCallback %d\n", expectedCallback); } break; } ca_flush_io(); if(verbose) { printTime(); printf("Issued ca_put_callback expectedCallback %d\n", expectedCallback); } while(1) { status = epicsEventWaitWithTimeout(pevent,10.0); if(status==epicsEventWaitTimeout) { if(verbose) { printTime(); printf("timeout after 10 seconds\n"); } continue; } break; } if(status!=epicsEventWaitOK) { int i; printTime(); printf("eventWait status %d\n",status); for(i=0; i<MAXnumberCallback; i++) numberCallback[i]=0; } epicsThreadSleep(sleepSecs); } } ca_task_exit(); return(0); }
int caget (pv *pvs, int nPvs, OutputT format, chtype dbrType, unsigned long reqElems) { unsigned int i; int n, result; for (n = 0; n < nPvs; n++) { /* Set up pvs structure */ /* -------------------- */ /* Get natural type and array count */ pvs[n].nElems = ca_element_count(pvs[n].chid); pvs[n].dbfType = ca_field_type(pvs[n].chid); pvs[n].dbrType = dbrType; /* Set up value structures */ pvs[n].dbrType = dbf_type_to_DBR_TIME(pvs[n].dbfType); /* Use native type */ if (dbr_type_is_ENUM(pvs[n].dbrType)) /* Enums honour -n option */ { if (enumAsNr) pvs[n].dbrType = DBR_TIME_INT; else pvs[n].dbrType = DBR_TIME_STRING; } if (reqElems == 0 || pvs[n].nElems < reqElems) /* Adjust array count */ pvs[n].reqElems = pvs[n].nElems; else pvs[n].reqElems = reqElems; /* Issue CA request */ /* ---------------- */ if (ca_state(pvs[n].chid) == cs_conn) { nConn++; pvs[n].onceConnected = 1; /* Allocate value structure */ pvs[n].value = calloc(1, dbr_size_n(pvs[n].dbrType, pvs[n].reqElems)); if(!pvs[n].value){ fprintf(stderr,"Allocation failed\n"); exit(1); } result = ca_array_get(pvs[n].dbrType, pvs[n].reqElems, pvs[n].chid, pvs[n].value); pvs[n].status = result; } else { pvs[n].status = ECA_DISCONN; } } if (!nConn) return 1; /* No connection? We're done. */ /* Wait for completion */ /* ------------------- */ result = ca_pend_io(caTimeout); if (result == ECA_TIMEOUT) fprintf(stderr, "Read operation timed out: PV data was not read.\n"); /* Print the data */ /* -------------- */ for (n = 0; n < nPvs; n++) { switch (format) { case plain: /* Emulate old caput behaviour */ if (pvs[n].reqElems <= 1 && fieldSeparator == ' ') printf("%-30s", pvs[n].name); else printf("%s", pvs[n].name); printf("%c", fieldSeparator); case terse: if (pvs[n].status == ECA_DISCONN) printf("*** not connected\n"); else if (pvs[n].status == ECA_NORDACCESS) printf("*** no read access\n"); else if (pvs[n].status != ECA_NORMAL) printf("*** CA error %s\n", ca_message(pvs[n].status)); else if (pvs[n].value == 0) printf("*** no data available (timeout)\n"); else { if (charArrAsStr && dbr_type_is_CHAR(pvs[n].dbrType) && (reqElems || pvs[n].reqElems > 1)) { dbr_char_t *s = (dbr_char_t*) dbr_value_ptr(pvs[n].value, pvs[n].dbrType); int dlen = epicsStrnEscapedFromRawSize((char*)s, strlen((char*)s)); char *d = calloc(dlen+1, sizeof(char)); if(!d){ fprintf(stderr,"Allocation failed\n"); exit(1); } epicsStrnEscapedFromRaw(d, dlen+1, (char*)s, strlen((char*)s)); printf("%s", d); free(d); } else { if (reqElems || pvs[n].nElems > 1) printf("%lu%c", pvs[n].reqElems, fieldSeparator); for (i=0; i<pvs[n].reqElems; ++i) { if (i) printf ("%c", fieldSeparator); printf("%s", val2str(pvs[n].value, pvs[n].dbrType, i)); } } printf("\n"); } break; case all: print_time_val_sts(&pvs[n], reqElems); break; default : break; } } return 0; }
int main (int argc, char *argv[]) { int i; int result; /* CA result */ OutputT format = plain; /* User specified format */ RequestT request = get; /* User specified request type */ int isArray = 0; /* Flag for array operation */ int enumAsString = 0; /* Force ENUM values to be strings */ int count = 1; int opt; /* getopt() current option */ chtype dbrType = DBR_STRING; char *pend; EpicsStr *sbuf; double *dbuf; char *cbuf = 0; char *ebuf = 0; void *pbuf; int len = 0; int waitStatus; struct dbr_gr_enum bufGrEnum; int nPvs; /* Number of PVs */ pv* pvs; /* Array of PV structures */ LINE_BUFFER(stdout); /* Configure stdout buffering */ putenv("POSIXLY_CORRECT="); /* Behave correct on GNU getopt systems */ while ((opt = getopt(argc, argv, ":cnlhatsS#:w:p:F:")) != -1) { switch (opt) { case 'h': /* Print usage */ usage(); return 0; case 'n': /* Force interpret ENUM as index number */ enumAsNr = 1; enumAsString = 0; break; case 's': /* Force interpret ENUM as menu string */ enumAsString = 1; enumAsNr = 0; break; case 'S': /* Treat char array as (long) string */ charArrAsStr = 1; isArray = 0; break; case 't': /* Select terse output format */ format = terse; break; case 'l': /* Select long output format */ format = all; break; case 'a': /* Select array mode */ isArray = 1; charArrAsStr = 0; break; case 'c': /* Select put_callback mode */ request = callback; break; case 'w': /* Set CA timeout value */ if(epicsScanDouble(optarg, &caTimeout) != 1) { fprintf(stderr, "'%s' is not a valid timeout value " "- ignored. ('caput -h' for help.)\n", optarg); caTimeout = DEFAULT_TIMEOUT; } break; case '#': /* Array count */ if (sscanf(optarg,"%d", &count) != 1) { fprintf(stderr, "'%s' is not a valid array element count " "- ignored. ('caput -h' for help.)\n", optarg); count = 0; } break; case 'p': /* CA priority */ if (sscanf(optarg,"%u", &caPriority) != 1) { fprintf(stderr, "'%s' is not a valid CA priority " "- ignored. ('caget -h' for help.)\n", optarg); caPriority = DEFAULT_CA_PRIORITY; } if (caPriority > CA_PRIORITY_MAX) caPriority = CA_PRIORITY_MAX; break; case 'F': /* Store this for output and tool_lib formatting */ fieldSeparator = (char) *optarg; break; case '?': fprintf(stderr, "Unrecognized option: '-%c'. ('caput -h' for help.)\n", optopt); return 1; case ':': fprintf(stderr, "Option '-%c' requires an argument. ('caput -h' for help.)\n", optopt); return 1; default : usage(); return 1; } } nPvs = argc - optind; /* Remaining arg list are PV names and values */ if (nPvs < 1) { fprintf(stderr, "No pv name specified. ('caput -h' for help.)\n"); return 1; } if (nPvs == 1) { fprintf(stderr, "No value specified. ('caput -h' for help.)\n"); return 1; } nPvs = 1; /* One PV - the rest is value(s) */ epId = epicsEventCreate(epicsEventEmpty); /* Create empty EPICS event (semaphore) */ /* Start up Channel Access */ result = ca_context_create(ca_enable_preemptive_callback); if (result != ECA_NORMAL) { fprintf(stderr, "CA error %s occurred while trying " "to start channel access.\n", ca_message(result)); return 1; } /* Allocate PV structure array */ pvs = calloc (nPvs, sizeof(pv)); if (!pvs) { fprintf(stderr, "Memory allocation for channel structure failed.\n"); return 1; } /* Connect channels */ pvs[0].name = argv[optind] ; /* Copy PV name from command line */ result = connect_pvs(pvs, nPvs); /* If the connection fails, we're done */ if (result) { ca_context_destroy(); return result; } /* Get values from command line */ optind++; if (isArray) { optind++; /* In case of array skip first value (nr * of elements) - actual number of values is used */ count = argc - optind; } else { /* Concatenate the remaining line to one string * (sucks but is compatible to the former version) */ for (i = optind; i < argc; i++) { len += strlen(argv[i]); len++; } cbuf = calloc(len, sizeof(char)); if (!cbuf) { fprintf(stderr, "Memory allocation failed.\n"); return 1; } strcpy(cbuf, argv[optind]); if (argc > optind+1) { for (i = optind + 1; i < argc; i++) { strcat(cbuf, " "); strcat(cbuf, argv[i]); } } if ((argc - optind) >= 1) count = 1; argv[optind] = cbuf; } sbuf = calloc (count, sizeof(EpicsStr)); dbuf = calloc (count, sizeof(double)); if(!sbuf || !dbuf) { fprintf(stderr, "Memory allocation failed\n"); return 1; } /* ENUM? Special treatment */ if (ca_field_type(pvs[0].chid) == DBR_ENUM) { /* Get the ENUM strings */ result = ca_array_get (DBR_GR_ENUM, 1, pvs[0].chid, &bufGrEnum); result = ca_pend_io(caTimeout); if (result == ECA_TIMEOUT) { fprintf(stderr, "Read operation timed out: ENUM data was not read.\n"); return 1; } if (enumAsNr) { /* Interpret values as numbers */ for (i = 0; i < count; ++i) { dbuf[i] = epicsStrtod(*(argv+optind+i), &pend); if (*(argv+optind+i) == pend) { /* Conversion didn't work */ fprintf(stderr, "Enum index value '%s' is not a number.\n", *(argv+optind+i)); return 1; } if (dbuf[i] >= bufGrEnum.no_str) { fprintf(stderr, "Warning: enum index value '%s' may be too large.\n", *(argv+optind+i)); } } dbrType = DBR_DOUBLE; } else { /* Interpret values as strings */ for (i = 0; i < count; ++i) { epicsStrnRawFromEscaped(sbuf[i], sizeof(EpicsStr), *(argv+optind+i), sizeof(EpicsStr)); *( sbuf[i]+sizeof(EpicsStr)-1 ) = '\0'; dbrType = DBR_STRING; /* Compare to ENUM strings */ for (len = 0; len < bufGrEnum.no_str; len++) if (!strcmp(sbuf[i], bufGrEnum.strs[len])) break; if (len >= bufGrEnum.no_str) { /* Not a string? Try as number */ dbuf[i] = epicsStrtod(sbuf[i], &pend); if (sbuf[i] == pend || enumAsString) { fprintf(stderr, "Enum string value '%s' invalid.\n", sbuf[i]); return 1; } if (dbuf[i] >= bufGrEnum.no_str) { fprintf(stderr, "Warning: enum index value '%s' may be too large.\n", sbuf[i]); } dbrType = DBR_DOUBLE; } } } } else { /* Not an ENUM */ if (charArrAsStr) { dbrType = DBR_CHAR; ebuf = calloc(len, sizeof(char)); if(!ebuf) { fprintf(stderr, "Memory allocation failed\n"); return 1; } count = epicsStrnRawFromEscaped(ebuf, len, cbuf, len-1) + 1; } else { for (i = 0; i < count; ++i) { epicsStrnRawFromEscaped(sbuf[i], sizeof(EpicsStr), *(argv+optind+i), sizeof(EpicsStr)); *( sbuf[i]+sizeof(EpicsStr)-1 ) = '\0'; } dbrType = DBR_STRING; } } /* Read and print old data */ if (format != terse) { printf("Old : "); result = caget(pvs, nPvs, format, 0, 0); } /* Write new data */ if (dbrType == DBR_STRING) pbuf = sbuf; else if (dbrType == DBR_CHAR) pbuf = ebuf; else pbuf = dbuf; if (request == callback) { /* Use callback version of put */ pvs[0].status = ECA_NORMAL; /* All ok at the moment */ result = ca_array_put_callback ( dbrType, count, pvs[0].chid, pbuf, put_event_handler, (void *) pvs); } else { /* Use standard put with defined timeout */ result = ca_array_put (dbrType, count, pvs[0].chid, pbuf); } result = ca_pend_io(caTimeout); if (result == ECA_TIMEOUT) { fprintf(stderr, "Write operation timed out: Data was not written.\n"); return 1; } if (request == callback) { /* Also wait for callbacks */ waitStatus = epicsEventWaitWithTimeout( epId, caTimeout ); if (waitStatus) fprintf(stderr, "Write callback operation timed out\n"); /* retrieve status from callback */ result = pvs[0].status; } if (result != ECA_NORMAL) { fprintf(stderr, "Error occured writing data.\n"); return 1; } /* Read and print new data */ if (format != terse) printf("New : "); result = caget(pvs, nPvs, format, 0, 0); /* Shut down Channel Access */ ca_context_destroy(); return result; }
void SinglePlotThread::run() { #if 0 // event gathering //printchannel(); //for Debug mutex.lock(); mynode.plot = m_plot; chid unit_chid; dbr_string_t units; QString unitch = m_pvname + ".EGU"; ca_create_channel(unitch.toStdString().c_str(), 0, 0, 0, &unit_chid); ca_pend_io(0.1); ca_get(DBR_STRING, unit_chid, (void *)&units); ca_pend_io(0.1); m_plot->SetUnit(units); ca_create_channel(m_pvname.toStdString().c_str(), connectionCallback, &mynode, 0, (oldChannelNotify**)&mynode.mychid); ca_replace_access_rights_event(mynode.mychid, accessRightsCallback); ca_create_subscription (DBR_TIME_DOUBLE, 0, mynode.mychid, DBE_VALUE|DBE_ALARM, eventCallback, &mynode, &mynode.myevid); //ca_add_event(DBR_GR_DOUBLE, mynode.mychid, eventCallback, &mynode, &mynode.myevid); mutex.unlock(); ca_pend_event(0.0); #else //periodic gathering mutex.lock(); chid unit_chid, val_chid; dbr_string_t units; QString unitch = m_pvname + ".EGU"; ca_create_channel(unitch.toStdString().c_str(), 0, 0, 0, &unit_chid); ca_pend_io(0.2); ca_get(DBR_STRING, unit_chid, (void *)&units); ca_pend_io(0.2); m_plot->SetUnit(units); struct dbr_time_double data; ca_create_channel(m_pvname.toStdString().c_str(), 0, 0, 0, &val_chid); ca_pend_io(0.2); epicsTime stamp; struct local_tm_nano_sec tm; int totsec = 0; //for periodic single plot local time int year, month, day, hour, min, sec; int factor = 1; switch(mperiodic) { case PointOne: factor *= 0.1; break; case PointFive: factor *= 0.5; break; case FiveSec: factor *= 5; break; case TenSec: factor *= 10; break; case OneSec: default: break; }; while(getStop()==false) { ca_get(DBR_TIME_DOUBLE, val_chid, (void *)&data); ca_pend_io(0.2); //qDebug("%s : %f\n",ca_name(val_chid), data.value); Epoch2Datetime(year, month, day, hour, min, sec); #if 0 stamp = data.stamp; tm = (local_tm_nano_sec) stamp; totsec = tm.ansi_tm.tm_hour*3600+tm.ansi_tm.tm_min*60+tm.ansi_tm.tm_sec; m_plot->GetValue(data.value, totsec,tm.ansi_tm.tm_year,tm.ansi_tm.tm_mon, tm.ansi_tm.tm_mday ); #else totsec = hour*3600+min*60+sec; m_plot->GetValue(data.value, totsec, year, month, day); #endif usleep(1000000*factor); }; //ca_clear_channel(unit_chid); //ca_clear_channel(val_chid); ca_context_destroy(); mutex.unlock(); exit(); qDebug("SinglePlot Exit"); #endif }
/* Find an unconnected PV and attempt to connect to it. That should * restart the searches for all other unresolved PVs. */ void retryConnections(void) { int i,j; const char *pvname=NULL; chid retryChid; int status; #if DEBUG_RETRY print("retryConnections:\n"); print(" freeListSize=%d freeListCount=%d\n", caTask.freeListSize,caTask.freeListCount); print(" pageSize=%d pageCount=%d\n", caTask.pageSize,caTask.pageCount); print(" nextpage=%d nextFree=%d\n", caTask.nextPage,caTask.nextFree); print(" channelCount=%d channelConnected=%d\n", caTask.channelCount,caTask.channelConnected); if(caTask.nextPage != caTask.pageCount-1) { print(" caTask.nextPage != caTask.pageCount-1\n"); } #else /* Check if all channels are connected */ if(caTask.channelCount == caTask.channelConnected) { medmPostMsg(1,"retryConnections: All channels are connected\n"); XBell(display, 50); return; } #endif /* Find an unconnected PV */ for(i=0; i < caTask.pageCount; i++) { int jmax=(i == caTask.nextPage)?caTask.nextFree:CA_PAGE_SIZE; for(j=0; j < jmax; j++) { Channel *pCh=&caTask.pages[i][j]; if(pCh->chid && ca_state(pCh->chid) != cs_conn) { pvname=ca_name(pCh->chid); break; } } if(pvname) break; } #if DEBUG_RETRY print(" Found %s\n",pvname?pvname:"Not found"); if(!pvname) return; #else if(!pvname) { medmPostMsg(1,"retryConnections: Failed to find unconnected PV\n"); return; } #endif /* Search */ status=ca_search_and_connect(pvname,&retryChid,NULL,NULL); if(status != ECA_NORMAL) { medmPostMsg(1,"retryConnections: ca_search failed for %s: %s\n", pvname, ca_message(status)); } /* Wait. The searches will only continue for this time. Keep the * time short as the interface is frozen, and most of the searches * occur at the start of the sequence. Testing indicated: * * RETRY_TIMEOUT Searches * 30 15 * 5 10 * 3 9 * 2 9 * 1 8 * * but this may vary owing to tuning and may change with new releases. */ ca_pend_io(RETRY_TIMEOUT); /* Clear the channel */ status = ca_clear_channel(retryChid); if(status != ECA_NORMAL) { medmPostMsg(1,"retryConnections: ca_clear_channel failed for %s: %s\n", pvname, ca_message(status)); } }