@@ -598,7 +598,6 @@ class MultiFunction : public asynPortDriver {
598598 virtual asynStatus writeInt32 (asynUser *pasynUser, epicsInt32 value);
599599 virtual asynStatus getBounds (asynUser *pasynUser, epicsInt32 *low, epicsInt32 *high);
600600 virtual asynStatus writeFloat64 (asynUser *pasynUser, epicsFloat64 value);
601- virtual asynStatus readFloat64 (asynUser *pasynUser, epicsFloat64 *value);
602601 virtual asynStatus writeUInt32Digital (asynUser *pasynUser, epicsUInt32 value, epicsUInt32 mask);
603602 virtual asynStatus readFloat32Array (asynUser *pasynUser, epicsFloat32 *value, size_t nElements, size_t *nIn);
604603 virtual asynStatus writeFloat32Array (asynUser *pasynUser, epicsFloat32 *value, size_t nElements);
@@ -726,6 +725,8 @@ class MultiFunction : public asynPortDriver {
726725 int boardFamily_;
727726 const boardEnums_t *pBoardEnums_;
728727 int numAnalogIn_;
728+ int numVoltageIn_;
729+ int numTemperatureIn_;
729730 int analogInTypeConfigurable_;
730731 int analogInDataRateConfigurable_;
731732 int analogOutRangeConfigurable_;
@@ -742,7 +743,6 @@ class MultiFunction : public asynPortDriver {
742743 int firstCounter_;
743744 int numTimers_;
744745 int numIOPorts_;
745- int numTempChans_;
746746 int digitalIOPort_[MAX_IO_PORTS];
747747 int digitalIOBitConfigurable_[MAX_IO_PORTS];
748748 int digitalIOPortConfigurable_[MAX_IO_PORTS];
@@ -1014,7 +1014,7 @@ MultiFunction::MultiFunction(const char *portName, const char *uniqueID, int max
10141014 cbGetConfig (BOARDINFO, boardNum_, 0 , BIADRES, &ADCResolution_);
10151015 cbGetConfig (BOARDINFO, boardNum_, 0 , BIDACRES, &DACResolution_);
10161016 cbGetConfig (BOARDINFO, boardNum_, 0 , BIDINUMDEVS, &numIOPorts_);
1017- cbGetConfig (BOARDINFO, boardNum_, 0 , BINUMTEMPCHANS, &numTempChans_ );
1017+ cbGetConfig (BOARDINFO, boardNum_, 0 , BINUMTEMPCHANS, &numTemperatureIn_ );
10181018 #else
10191019 long long infoValue;
10201020 status = ulAIGetInfo (daqDeviceHandle_, AI_INFO_NUM_CHANS_BY_TYPE, AI_VOLTAGE, &infoValue);
@@ -1034,7 +1034,7 @@ MultiFunction::MultiFunction(const char *portName, const char *uniqueID, int max
10341034 status = ulDIOGetInfo (daqDeviceHandle_, DIO_INFO_NUM_PORTS, 0 , &infoValue);
10351035 numIOPorts_ = infoValue;
10361036 status = ulAIGetInfo (daqDeviceHandle_, AI_INFO_NUM_CHANS_BY_TYPE, AI_TC, &infoValue);
1037- numTempChans_ = infoValue;
1037+ numTemperatureIn_ = infoValue;
10381038 #endif
10391039 if (numIOPorts_ > MAX_IO_PORTS) numIOPorts_ = MAX_IO_PORTS;
10401040 for (i=0 ; i<numIOPorts_; i++) {
@@ -1258,7 +1258,7 @@ MultiFunction::MultiFunction(const char *portName, const char *uniqueID, int max
12581258 setIntegerParam (waveDigRun_, 0 );
12591259 setIntegerParam (waveGenRun_, 0 );
12601260 setDoubleParam (pollSleepMS_, 50 .);
1261- for (i=0 ; i<numTempChans_ ; i++) {
1261+ for (i=0 ; i<numTemperatureIn_ ; i++) {
12621262 setIntegerParam (i, thermocoupleType_, TC_TYPE_J);
12631263 }
12641264 // Set the analog output range to the first supported value for this model
@@ -2249,106 +2249,6 @@ asynStatus MultiFunction::writeFloat64(asynUser *pasynUser, epicsFloat64 value)
22492249 return (status==0 ) ? asynSuccess : asynError;
22502250}
22512251
2252- asynStatus MultiFunction::readFloat64 (asynUser *pasynUser, epicsFloat64 *value)
2253- {
2254- int addr;
2255- int function = pasynUser->reason ;
2256- int status=0 ;
2257- int type;
2258- int scale;
2259- int filter=0 ;
2260- int range;
2261- static const char *functionName = " readFloat64" ;
2262-
2263- this ->getAddress (pasynUser, &addr);
2264-
2265- // Temperature input function
2266- if (function == temperatureInValue_) {
2267- if (waveDigRunning_) {
2268- int currentPoint;
2269- getIntegerParam (waveDigCurrentPoint_, ¤tPoint);
2270- if (currentPoint > 0 ) {
2271- *value = waveDigBuffer_[addr][currentPoint-1 ];
2272- }
2273- }
2274- else {
2275- getIntegerParam (addr, analogInType_, &type);
2276- getIntegerParam (addr, temperatureScale_, &scale);
2277- getIntegerParam (addr, temperatureFilter_, &filter);
2278- if (type != AI_CHAN_TYPE_TC) return asynSuccess;
2279- ULMutex.lock ();
2280- #ifdef _WIN32
2281- float fVal ;
2282- status = cbTIn (boardNum_, addr, scale, &fVal , filter);
2283- if (status == OPENCONNECTION) {
2284- // This is an "expected" error if the thermocouple is broken or disconnected
2285- // Don't print error message, just set temp to -9999.
2286- fVal = -9999 .;
2287- status = 0 ;
2288- *value = (double ) fVal ;
2289- }
2290- *value = (double ) fVal ;
2291- #else
2292- TempScale tempScale;
2293- // cbTin has a filter option but ulTin does not?
2294- TInFlag flags = TIN_FF_DEFAULT;
2295- switch (scale) {
2296- case CELSIUS: tempScale = TS_CELSIUS; break ;
2297- case FAHRENHEIT: tempScale = TS_FAHRENHEIT; break ;
2298- case KELVIN: tempScale = TS_KELVIN; break ;
2299- case VOLTS: tempScale = TS_VOLTS; break ;
2300- case NOSCALE: tempScale = TS_NOSCALE; break ;
2301- default :
2302- asynPrint (pasynUserSelf, ASYN_TRACE_ERROR,
2303- " %s::%s unsupported Scale=%d\n " , driverName, functionName, scale);
2304- tempScale = TS_CELSIUS;
2305- }
2306- status = ulTIn (daqDeviceHandle_, addr, tempScale, flags, value);
2307- if (status == ERR_OPEN_CONNECTION) {
2308- // This is an "expected" error if the thermocouple is broken or disconnected
2309- // Don't print error message, just set temp to -9999.
2310- status = 0 ;
2311- *value = -9999 .;
2312- }
2313- #endif
2314- ULMutex.unlock ();
2315- }
2316- setDoubleParam (addr, temperatureInValue_, *value);
2317- reportError (status, functionName, " Calling TIn" );
2318- }
2319- else if (function == voltageInValue_) {
2320- getIntegerParam (addr, voltageInRange_, &range);
2321- ULMutex.lock ();
2322- #ifdef _WIN32
2323- float fVal ;
2324- status = cbVIn (boardNum_, addr, range, &fVal , 0 );
2325- *value = fVal ;
2326- #else
2327- double data;
2328- Range ulRange;
2329- mapRange (range, &ulRange);
2330- int chan = addr;
2331- if (boardFamily_ == USB_TEMP_AI) {
2332- // On Linux the address needs to be 4 larger
2333- chan = addr + 4 ;
2334- }
2335- status = ulAIn (daqDeviceHandle_, chan, aiInputMode_, ulRange, AIN_FF_DEFAULT, &data);
2336- *value = (float ) data;
2337- #endif
2338- ULMutex.unlock ();
2339- reportError (status, functionName, " Calling AIn" );
2340- setDoubleParam (addr, voltageInValue_, *value);
2341- }
2342-
2343- // Other functions we call the base class method
2344- else {
2345- status = asynPortDriver::readFloat64 (pasynUser, value);
2346- }
2347-
2348- callParamCallbacks (addr);
2349- return (status==0 ) ? asynSuccess : asynError;
2350- }
2351-
23522252asynStatus MultiFunction::writeUInt32Digital (asynUser *pasynUser, epicsUInt32 value, epicsUInt32 mask)
23532253{
23542254 int function = pasynUser->reason ;
@@ -2606,6 +2506,8 @@ void MultiFunction::pollerThread()
26062506 epicsUInt32 countVal;
26072507 long aoCount, aoIndex, aiCount, aiIndex;
26082508 short aoStatus, aiStatus;
2509+ int scale;
2510+ int filter=0 ;
26092511 epicsTime startTime=epicsTime::getCurrent (), endTime, currentTime;
26102512 int lastPoint;
26112513 int status=0 , prevStatus=0 ;
@@ -2751,32 +2653,97 @@ void MultiFunction::pollerThread()
27512653 // If the waveform digitizer is not running then read the analog inputs
27522654 int range, type, mode;
27532655 epicsInt32 value;
2656+ double tempValue;
27542657 getIntegerParam (0 , analogInMode_, &mode);
27552658 for (i=0 ; i<numAnalogIn_; i++) {
27562659 getIntegerParam (i, analogInRange_, &range);
27572660 getIntegerParam (i, analogInType_, &type);
27582661 if (type != AI_CHAN_TYPE_VOLTAGE) continue ;
27592662 if ((boardType_ == E_1608) && (mode == DIFFERENTIAL) && (i>3 )) break ;
2663+ if (boardType_ == USB_TEMP_AI) {
2664+ // USB_TEMP_AI reads voltage as floating point
2665+ #ifdef _WIN32
2666+ float fVal ;
2667+ status = cbVIn (boardNum_, i, range, &fVal , 0 );
2668+ tempValue = fVal ;
2669+ #else
2670+ Range ulRange;
2671+ mapRange (range, &ulRange);
2672+ // On Linux the address needs to be 4 larger
2673+ status = ulAIn (daqDeviceHandle_, i+4 , aiInputMode_, ulRange, AIN_FF_DEFAULT, &tempValue);
2674+ #endif
2675+ reportError (status, functionName, " Calling AIn" );
2676+ setDoubleParam (i, voltageInValue_, tempValue);
2677+ }
2678+ else {
2679+ // Models other than USB_TEMP_AI read voltage as integer
2680+ #ifdef _WIN32
2681+ if (ADCResolution_ <= 16 ) {
2682+ epicsUInt16 shortVal;
2683+ status = cbAIn (boardNum_, i, range, &shortVal);
2684+ value = shortVal;
2685+ } else {
2686+ ULONG ulongVal;
2687+ status = cbAIn32 (boardNum_, i, range, &ulongVal, 0 );
2688+ value = (epicsInt32)ulongVal;
2689+ }
2690+ #else
2691+ double data;
2692+ Range ulRange;
2693+ mapRange (range, &ulRange);
2694+ status = ulAIn (daqDeviceHandle_, i, aiInputMode_, ulRange, AIN_FF_NOSCALEDATA, &data);
2695+ value = (epicsInt32) data;
2696+ #endif
2697+ setIntegerParam (i, analogInValue_, value);
2698+ }
2699+ } // for numAnalogIn_
2700+
2701+ for (i=0 ; i<numTemperatureIn_; i++) {
2702+ getIntegerParam (i, analogInRange_, &range);
2703+ getIntegerParam (i, analogInType_, &type);
2704+ if (type != AI_CHAN_TYPE_TC) continue ;
2705+ getIntegerParam (i, temperatureScale_, &scale);
2706+ getIntegerParam (i, temperatureFilter_, &filter);
27602707 #ifdef _WIN32
2761- if (ADCResolution_ <= 16 ) {
2762- epicsUInt16 shortVal;
2763- status = cbAIn (boardNum_, i, range, &shortVal);
2764- value = shortVal;
2765- } else {
2766- ULONG ulongVal;
2767- status = cbAIn32 (boardNum_, i, range, &ulongVal, 0 );
2768- value = (epicsInt32)ulongVal;
2708+ float fVal ;
2709+ status = cbTIn (boardNum_, i, scale, &fVal , filter);
2710+ if (status == OPENCONNECTION) {
2711+ // This is an "expected" error if the thermocouple is broken or disconnected
2712+ // Don't print error message, just set temp to -9999.
2713+ fVal = -9999 .;
2714+ status = 0 ;
27692715 }
2716+ tempValue = (double ) fVal ;
27702717 #else
2771- double data;
2772- Range ulRange;
2773- mapRange (range, &ulRange);
2774- status = ulAIn (daqDeviceHandle_, i, aiInputMode_, ulRange, AIN_FF_NOSCALEDATA, &data);
2775- value = (epicsInt32) data;
2718+ TempScale tempScale;
2719+ // cbTin has a filter option but ulTin does not?
2720+ TInFlag flags = TIN_FF_DEFAULT;
2721+ switch (scale) {
2722+ case CELSIUS: tempScale = TS_CELSIUS; break ;
2723+ case FAHRENHEIT: tempScale = TS_FAHRENHEIT; break ;
2724+ case KELVIN: tempScale = TS_KELVIN; break ;
2725+ case VOLTS: tempScale = TS_VOLTS; break ;
2726+ case NOSCALE: tempScale = TS_NOSCALE; break ;
2727+ default :
2728+ asynPrint (pasynUserSelf, ASYN_TRACE_ERROR,
2729+ " %s::%s unsupported Scale=%d\n " , driverName, functionName, scale);
2730+ tempScale = TS_CELSIUS;
2731+ }
2732+ status = ulTIn (daqDeviceHandle_, i, tempScale, flags, &tempValue);
2733+ if (status == ERR_OPEN_CONNECTION) {
2734+ // This is an "expected" error if the thermocouple is broken or disconnected
2735+ // Don't print error message, just set temp to -9999.
2736+ status = 0 ;
2737+ tempValue = -9999 .;
2738+ }
27762739 #endif
2777- setIntegerParam (i, analogInValue_, value);
2778- }
2779- }
2740+ // if (i==0) asynPrint(pasynUserSelf, ASYN_TRACE_ERROR, "ulTIn chan=%d, tempValue=%f\n", i, tempValue);
2741+
2742+ setDoubleParam (i, temperatureInValue_, tempValue);
2743+ reportError (status, functionName, " Calling TIn" );
2744+
2745+ } // for on channels
2746+ } // waveDig not running
27802747
27812748 for (i=0 ; i<MAX_SIGNALS; i++) {
27822749 callParamCallbacks (i);
@@ -2808,7 +2775,7 @@ void MultiFunction::report(FILE *fp, int details)
28082775 fprintf (fp, " analog input bits = %d\n " , ADCResolution_);
28092776 fprintf (fp, " analog outputs = %d\n " , numAnalogOut_);
28102777 fprintf (fp, " analog output bits = %d\n " , DACResolution_);
2811- fprintf (fp, " temperature inputs = %d\n " , numTempChans_ );
2778+ fprintf (fp, " temperature inputs = %d\n " , numTemperatureIn_ );
28122779 fprintf (fp, " digital I/O ports = %d\n " , numIOPorts_);
28132780 for (i=0 ; i<numIOPorts_; i++) {
28142781 fprintf (fp, " digital I/O port %d\n " , i);
0 commit comments