#include /************************************************************************/ /* */ /* This module shows you how to perform an asynchronous timed analog */ /* acquisition. */ /* */ /* The acquisition and plotting is performed in AITimerCallback(). */ /* */ /************************************************************************/ #include /* Needed if linking in external compiler; harmless otherwise */ #include #include #include #include #include "easyio.h" #include "ai_async.h" #include "ai_log.h" static int AIRestartDAQ(void); static int AIReadDAQ(void); static void AIDisplayError (short error); static void SetAutoTrigger (void); /**** globals shared with ao_wave.c, ai_log.c, and ai_cmd.c ****/ int ai_main (int argc, char *argv[]); int gAIpanelHandle = 0; int gAIlogging = 0; int gAIcmdEditHandle; /****************************************************************/ static const int CIRC_BUF_SIZE = 8000; static int asyncRunning = 0; static long AIerror = 0; static unsigned long AItaskID = 0; static double * AIwaveforms = 0; static int AIhelpHandle; static int AItriggerHandle; static int AIrestart = 1; static short AIdevice; static long AIbacklog; static unsigned long AInumChannels = 1; static long AInumScans = 300; static char AIchannelString[100]; static double upper; static double lower; static double AIscanRate; static double actualAIscanRate; static unsigned short AIreadMode; static int displayOverWriteOccurred = 0; static int firstTimeThrough = 1; static long preTriggerScans; static char triggerSource[30]; static unsigned short trigger_edge_slope; static unsigned short triggerType = NO_TRIGGER; static double triggerLevel; static int inTriggerMode = 0; static int needToAutoTrigger = 0; static int ColorArray[8] = {VAL_GREEN, VAL_YELLOW, VAL_CYAN, VAL_WHITE, VAL_BLUE, VAL_MAGENTA, VAL_GRAY, VAL_RED}; static char projDir [MAX_PATHNAME_LEN]; static char triggerFileName [MAX_PATHNAME_LEN]; static int previousBOLEstate; #if defined(AO_WAVE) || defined(AI_LOG) || defined(CTR_PULS_PRJ) int ai_main (int argc, char *argv[]) { #else int main (int argc, char *argv[]) { int AIerror; double result; if (InitCVIRTE (0, argv, 0) == 0) /* Needed if linking in external compiler; harmless otherwise */ return -1; /* out of memory */ #endif gAIpanelHandle = LoadPanel (0, "ai_async.uir", AI_PANEL); AIhelpHandle = LoadPanel (0, "ai_async.uir", AI_HELP); AItriggerHandle = LoadPanel (0, "ai_async.uir", TRIGGERING); AIwaveforms = malloc (1000 * sizeof(double)); /* use realloc() elsewhere */ /*--------------------------------------------------------------*/ /* This is the line I entered to allocate memory on the MIO card */ /* It should be implemened in the setup of the device */ AIerror = Set_DAQ_Device_Info (1, ND_VXIMIO_SET_ALLOCATE_MODE, ND_VXIMIO_USE_ONBOARD_MEMORY_AI); /* ------------------------------------------------------------------*/ AILimitCallback (gAIpanelHandle, AI_PANEL_UPPER, EVENT_VAL_CHANGED, 0, 0, 0); AILimitCallback (gAIpanelHandle, AI_PANEL_LOWER, EVENT_VAL_CHANGED, 0, 0, 0); AIScanRateCallback (gAIpanelHandle, AI_PANEL_SCANRATE, EVENT_VAL_CHANGED, 0, 0, 0); AINumScansCallback (gAIpanelHandle, AI_PANEL_NUMSCANS, EVENT_VAL_CHANGED, 0, 0, 0); AIReadModeCallback (gAIpanelHandle, AI_PANEL_READMODE, EVENT_COMMIT, 0, 0, 0); AIChannelCallback (gAIpanelHandle, AI_PANEL_CHANNEL, EVENT_COMMIT, 0, 0, 0); SetCtrlAttribute (gAIpanelHandle, AI_PANEL_CLEAR, ATTR_VISIBLE, 0); SetCtrlAttribute (gAIpanelHandle, AI_PANEL_LOGBUTTON, ATTR_VISIBLE, 0); SetCtrlAttribute (gAIpanelHandle, AI_PANEL_LOGCONFIG, ATTR_VISIBLE, 0); GetProjectDir (projDir); MakePathname (projDir, "trigger.st", triggerFileName); SavePanelState (AItriggerHandle, triggerFileName, 0); #if defined (AO_WAVE) || defined (AI_LOG) || defined (CTR_PULS_PRJ) return 0; #endif #ifdef AI_CMD gAIcmdEditHandle = LoadPanel (0, "ai_async.uir", CMDEDIT); SetPanelPos (gAIcmdEditHandle, 30, VAL_AUTO_CENTER); DisplayPanel (gAIcmdEditHandle); SetPanelPos (gAIpanelHandle, 180, VAL_AUTO_CENTER); #endif DisplayPanel (gAIpanelHandle); RunUserInterface (); return 0; } int CVICALLBACK AIChannelCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_RIGHT_CLICK: DisplayPanel(AIhelpHandle); break; case EVENT_COMMIT: GetCtrlVal (gAIpanelHandle, AI_PANEL_CHANNEL, AIchannelString); previousBOLEstate = GetBreakOnLibraryErrors (); if (previousBOLEstate) DisableBreakOnLibraryErrors(); ///////////////////////////////////////////////////////////////////// // these calls should later be replaced by a utility function // // to get the number of channels from a channel string // nidaqAIStop (AItaskID); nidaqAIDestroyTask (AItaskID); nidaqAICreateTask (AIchannelString, kNidaqPointByPoint, &AInumChannels, &AItaskID); nidaqAIDestroyTask (AItaskID); ///////////////////////////////////////////////////////////////////// AIDisplayError (AIerror); GetCtrlVal (AItriggerHandle, TRIGGERING_SOURCE, triggerSource); if (previousBOLEstate) EnableBreakOnLibraryErrors(); AIDisplayError (AIerror); AIwaveforms = realloc (AIwaveforms, AInumScans * AInumChannels * sizeof (double)); if (AIwaveforms == 0) { AIerror = memFullError; AIDisplayError (AIerror); } else { memset (AIwaveforms, 0, AInumScans * AInumChannels * sizeof (double)); needToAutoTrigger = 1; } AIrestart = 1; break; } return 0; } int CVICALLBACK AIChannelRingCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { char * str; switch (event) { static int index; static int length; case EVENT_COMMIT: GetCtrlIndex (gAIpanelHandle, AI_PANEL_CHANNELRING, &index); GetValueLengthFromIndex (gAIpanelHandle, AI_PANEL_CHANNELRING, index, &length); str = (char *) malloc (length+1); GetCtrlVal (gAIpanelHandle, AI_PANEL_CHANNELRING, str); ResetTextBox (gAIpanelHandle, AI_PANEL_CHANNEL, str); AIChannelCallback (gAIpanelHandle, AI_PANEL_CHANNEL, EVENT_COMMIT, 0, 0, 0); free (str); break; } return 0; } int CVICALLBACK AILimitCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_VAL_CHANGED: switch (control) { case AI_PANEL_UPPER: GetCtrlVal (gAIpanelHandle, AI_PANEL_UPPER, &upper); if (upper <= lower) { upper = lower + 1.0; SetCtrlVal (gAIpanelHandle, AI_PANEL_UPPER, upper); } break; case AI_PANEL_LOWER: GetCtrlVal (gAIpanelHandle, AI_PANEL_LOWER, &lower); if (upper <= lower) { lower = upper - 1.0; SetCtrlVal (gAIpanelHandle, AI_PANEL_LOWER, lower); } break; } SetAxisRange (gAIpanelHandle, AI_PANEL_GRAPH, VAL_NO_CHANGE, 0.0, 1.0, VAL_MANUAL, lower, upper); SetCtrlAttribute (gAIpanelHandle, AI_PANEL_TRIGGER_LEVEL, ATTR_MAX_VALUE, upper); SetCtrlAttribute (gAIpanelHandle, AI_PANEL_TRIGGER_LEVEL, ATTR_MIN_VALUE, lower); AIrestart = 1; break; } return 0; } int CVICALLBACK AIScanRateCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_VAL_CHANGED: GetCtrlVal (gAIpanelHandle, AI_PANEL_SCANRATE, &AIscanRate); AIrestart = 1; break; } return 0; } int CVICALLBACK AINumScansCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_VAL_CHANGED: GetCtrlVal (gAIpanelHandle, AI_PANEL_NUMSCANS, &AInumScans); AIwaveforms = realloc (AIwaveforms, AInumScans * AInumChannels * sizeof (double)); if (AIwaveforms != 0) { memset (AIwaveforms, 0, AInumScans * AInumChannels * sizeof (double)); } SetAxisRange (gAIpanelHandle, AI_PANEL_GRAPH, VAL_MANUAL, 0.0, AInumScans-1, VAL_NO_CHANGE, 0.0, 1.0); break; } return 0; } int CVICALLBACK AIReadModeCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_COMMIT: GetCtrlVal (gAIpanelHandle, AI_PANEL_READMODE, &AIreadMode); break; } return 0; } int CVICALLBACK AICloseHelpCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_COMMIT: HidePanel (AIhelpHandle); break; } return 0; } int CVICALLBACK AITimerCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { int i; switch (event) { case EVENT_TIMER_TICK: if (AIrestart) { AIerror = AIRestartDAQ(); if (AIerror < 0) { return 0; } } AIerror = AIReadDAQ(); if (AIerror < 0) { return 0; } #ifdef AI_LOG if (gAIlogging) { AIerror = LogWaveform (AIwaveforms, AInumScans * AInumChannels, AInumChannels); } #endif SetCtrlVal (gAIpanelHandle, AI_PANEL_BACKLOG, AIbacklog); AIerror = DeleteGraphPlot (gAIpanelHandle, AI_PANEL_GRAPH, -1, VAL_DELAYED_DRAW); SetCtrlAttribute (gAIpanelHandle, AI_PANEL_GRAPH, ATTR_REFRESH_GRAPH, 0); for (i=0; i= noError) { AIerror = nidaqAIConfigBuffer (AItaskID, CIRC_BUF_SIZE, kNidaqContinuous); AIerror = nidaqAIConfigScanClockRate (AItaskID, AIscanRate, &actualScanRate); switch (AIreadMode) { case kNidaqAtWriteMark: AIerror = nidaqAISetReadMarkMode (AItaskID, AIreadMode, -AInumScans); break; case kNidaqWhereItIsNow: AIerror = nidaqAISetReadMarkMode (AItaskID, AIreadMode, AInumScans); break; } AIerror = nidaqAIStart (AItaskID); if (triggerType == SW_ANALOG_TRIGGER) { AIerror = nidaqAISetConditionalRetrieval (AItaskID, triggerSource, trigger_edge_slope, triggerLevel, 0.0 /* hysteresis */, -preTriggerScans); } } ///////////////////////////////////////////////////////////////////// AIDisplayError (AIerror); if (AIerror < 0) { AIrestart = 1; } inTriggerMode = 0; } else { AIbacklog = 0; inTriggerMode = 1; } if (previousBOLEstate) EnableBreakOnLibraryErrors(); return AIerror; } static int AIReadDAQ(void) { double timeLimit = -1.0; long AIacqState; if (!inTriggerMode) { if (firstTimeThrough || (AIreadMode == kNidaqWhereItIsNow)) { previousBOLEstate = GetBreakOnLibraryErrors (); if (previousBOLEstate) DisableBreakOnLibraryErrors(); // old stuff //////////////////////////////////////////////////////// //AIerror = AICheckAcquisition (AItaskID, &AIbacklog); ///////////////////////////////////////////////////////////////////// // new stuff //////////////////////////////////////////////////////// AIerror = nidaqAICheck (AItaskID, &AIacqState, &AIbacklog); ///////////////////////////////////////////////////////////////////// if (previousBOLEstate) EnableBreakOnLibraryErrors(); AIDisplayError (AIerror); if (AIerror < 0) { AIrestart = 1; return (0); } if (AIbacklog < AInumScans) { SetCtrlVal (gAIpanelHandle, AI_PANEL_BACKLOG, AIbacklog); return (0); } } firstTimeThrough = 0; previousBOLEstate = GetBreakOnLibraryErrors (); if (previousBOLEstate) DisableBreakOnLibraryErrors(); // old stuff //////////////////////////////////////////////////////// //AIerror = AIReadAcquisition (AItaskID, AInumScans, AIreadMode, // &AIbacklog, GROUP_BY_CHANNEL, AIwaveforms); ///////////////////////////////////////////////////////////////////// // new stuff //////////////////////////////////////////////////////// AIerror = nidaqAICheck (AItaskID, &AIacqState, &AIbacklog); AIerror = nidaqAIRead (AItaskID, "", AInumScans, -1.0, AIwaveforms); ///////////////////////////////////////////////////////////////////// if (previousBOLEstate) EnableBreakOnLibraryErrors(); AIDisplayError (AIerror); if ((AIerror < 0) && (AIerror != timeOutError)) { AIrestart = 1; return (0); } SetCtrlVal (gAIpanelHandle, AI_PANEL_BACKLOG, AIbacklog); } else { previousBOLEstate = GetBreakOnLibraryErrors (); if (previousBOLEstate) DisableBreakOnLibraryErrors(); if (triggerType == HW_ANALOG_TRIGGER) { AIerror = nidaqAIAnalogTriggerScanOp (AIchannelString, AInumScans, AIscanRate, upper, lower, triggerLevel, trigger_edge_slope, triggerSource, 0.5 /* triggerWindow */, preTriggerScans, timeLimit, kNidaqGroupByChannel, &actualAIscanRate, AIwaveforms); } else { AIerror = nidaqAIDigitalTriggerScanOp (AIchannelString, AInumScans, AIscanRate, upper, lower, trigger_edge_slope, "", preTriggerScans, timeLimit, kNidaqGroupByChannel, &actualAIscanRate, AIwaveforms); } if (previousBOLEstate) EnableBreakOnLibraryErrors(); AIDisplayError (AIerror); if (AIerror < 0) { AIrestart = 1; return (0); } } return AIerror; } int CVICALLBACK ClearCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_COMMIT: displayOverWriteOccurred = 0; SetCtrlAttribute (gAIpanelHandle, AI_PANEL_ERRORBOX, ATTR_TEXT_COLOR, VAL_BLACK); ResetTextBox (gAIpanelHandle, AI_PANEL_ERRORBOX, "No Error."); SetCtrlAttribute (gAIpanelHandle, AI_PANEL_CLEAR, ATTR_VISIBLE, 0); AIDisplayError (0); break; } return 0; } int CVICALLBACK TriggeringCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_COMMIT: SavePanelState (AItriggerHandle, triggerFileName, 0); InstallPopup (AItriggerHandle); break; } return 0; } int CVICALLBACK TriggeringPopupCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { static long index[1]; unsigned short dummy_triggerType; switch (event) { case EVENT_COMMIT: switch (control) { case TRIGGERING_OK: case TRIGGERING_APPLY: GetCtrlVal (AItriggerHandle, TRIGGERING_TYPE, &triggerType); switch (triggerType) { case NO_TRIGGER: SetInputMode (gAIpanelHandle, AI_PANEL_TRIGGER_LEVEL, 0); SetInputMode (gAIpanelHandle, AI_PANEL_READMODE, 1); SetInputMode (gAIpanelHandle, AI_PANEL_BACKLOG, 1); break; case SW_ANALOG_TRIGGER: /* no break */ case HW_ANALOG_TRIGGER: GetCtrlVal (AItriggerHandle, TRIGGERING_EDGE_SLOPE, &trigger_edge_slope); GetCtrlVal (AItriggerHandle, TRIGGERING_PRETRIGGER_SCANS, &preTriggerScans); GetCtrlVal (AItriggerHandle, TRIGGERING_SOURCE, triggerSource); SetCtrlVal (gAIpanelHandle, AI_PANEL_READMODE, LATEST_MODE); SetInputMode (gAIpanelHandle, AI_PANEL_READMODE, 0); SetInputMode (gAIpanelHandle, AI_PANEL_BACKLOG, 0); SetInputMode (gAIpanelHandle, AI_PANEL_TRIGGER_LEVEL, 1); AIReadModeCallback (gAIpanelHandle, AI_PANEL_READMODE, EVENT_COMMIT, 0, 0, 0); break; default: GetCtrlVal (AItriggerHandle, TRIGGERING_EDGE_SLOPE, &trigger_edge_slope); GetCtrlVal (AItriggerHandle, TRIGGERING_PRETRIGGER_SCANS, &preTriggerScans); SetInputMode (gAIpanelHandle, AI_PANEL_TRIGGER_LEVEL, 0); if (triggerType == SCAN_CLOCK_GATING) { SetInputMode (gAIpanelHandle, AI_PANEL_READMODE, 1); } else { SetInputMode (gAIpanelHandle, AI_PANEL_READMODE, 0); } break; } if (control == TRIGGERING_OK) { RemovePopup (0); SetInputMode (AItriggerHandle, TRIGGERING_CANCEL, 1); } else { SetInputMode (AItriggerHandle, TRIGGERING_CANCEL, 0); SetInputMode (AItriggerHandle, TRIGGERING_APPLY, 0); } SavePanelState (AItriggerHandle, triggerFileName, 0); AIrestart = 1; break; case TRIGGERING_CANCEL: RemovePopup (0); RecallPanelState (AItriggerHandle, triggerFileName, 0); SetInputMode (AItriggerHandle, TRIGGERING_APPLY, 0); TriggeringPopupCallback (AItriggerHandle, TRIGGERING_TYPE, EVENT_COMMIT, 0, 0, 0); break; case TRIGGERING_TYPE: GetCtrlVal (AItriggerHandle, TRIGGERING_TYPE, &dummy_triggerType); switch (dummy_triggerType) { case NO_TRIGGER: SetInputMode (AItriggerHandle, TRIGGERING_EDGE_SLOPE, 0); SetInputMode (AItriggerHandle, TRIGGERING_SOURCE, 0); SetInputMode (AItriggerHandle, TRIGGERING_PRETRIGGER_SCANS, 0); break; case SW_ANALOG_TRIGGER: case HW_ANALOG_TRIGGER: SetInputMode (AItriggerHandle, TRIGGERING_EDGE_SLOPE, 1); SetInputMode (AItriggerHandle, TRIGGERING_SOURCE, 1); SetInputMode (AItriggerHandle, TRIGGERING_PRETRIGGER_SCANS, 1); needToAutoTrigger = 1; break; case DIGITAL_TRIGGER_A: SetInputMode (AItriggerHandle, TRIGGERING_EDGE_SLOPE, 1); SetInputMode (AItriggerHandle, TRIGGERING_SOURCE, 1); SetCtrlVal (AItriggerHandle, TRIGGERING_PRETRIGGER_SCANS, 0); SetInputMode (AItriggerHandle, TRIGGERING_PRETRIGGER_SCANS, 0); break; case DIGITAL_TRIGGER_AB: SetInputMode (AItriggerHandle, TRIGGERING_EDGE_SLOPE, 1); SetInputMode (AItriggerHandle, TRIGGERING_SOURCE, 1); SetInputMode (AItriggerHandle, TRIGGERING_PRETRIGGER_SCANS, 1); break; default: SetInputMode (AItriggerHandle, TRIGGERING_EDGE_SLOPE, 1); SetInputMode (AItriggerHandle, TRIGGERING_SOURCE, 0); SetInputMode (AItriggerHandle, TRIGGERING_PRETRIGGER_SCANS, 1); break; } default: if (control == TRIGGERING_SOURCE) { needToAutoTrigger = 1; } SetInputMode (AItriggerHandle, TRIGGERING_CANCEL, 1); SetInputMode (AItriggerHandle, TRIGGERING_APPLY, 1); break; } break; } return 0; } int CVICALLBACK TriggerLevelCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_VAL_CHANGED: SetCtrlAttribute (gAIpanelHandle, AI_PANEL_TIMER, ATTR_INTERVAL, 0.3); GetCtrlVal (gAIpanelHandle, AI_PANEL_TRIGGER_LEVEL, &triggerLevel); AIrestart = 1; break; case EVENT_COMMIT: SetCtrlAttribute (gAIpanelHandle, AI_PANEL_TIMER, ATTR_INTERVAL, 0.0); break; } return 0; } static void SetAutoTrigger () { enum {bufferSize = 800, maxChannels = 8}; static double wave[bufferSize]; double min; double max; int dummy; double highLimit, lowLimit; double sampleRate = 1000.0; AIerror = nidaqAIScanOp (AIchannelString, bufferSize/maxChannels, sampleRate, upper, lower, kNidaqGroupByChannel, &actualAIscanRate, wave); MaxMin1D (wave, bufferSize, &max, &dummy, &min, &dummy); triggerLevel = (max + min)/2.0; SetCtrlVal (gAIpanelHandle, AI_PANEL_TRIGGER_LEVEL, triggerLevel); } int CVICALLBACK QuitCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) { switch (event) { case EVENT_COMMIT: free (AIwaveforms); AIwaveforms = 0; previousBOLEstate = GetBreakOnLibraryErrors (); if (previousBOLEstate) DisableBreakOnLibraryErrors(); if (!inTriggerMode) { // old stuff //////////////////////////////////////////////////////// //AIClearAcquisition (AItaskID); ///////////////////////////////////////////////////////////////////// // new stuff //////////////////////////////////////////////////////// nidaqAIStop (AItaskID); nidaqAIDestroyTask (AItaskID); ///////////////////////////////////////////////////////////////////// } if (previousBOLEstate) EnableBreakOnLibraryErrors(); SetCtrlAttribute (gAIpanelHandle, AI_PANEL_TIMER, ATTR_ENABLED, 0); QuitUserInterface (0); break; } return 0; } static void AIDisplayError (short error) { static int lastError = 0; if (error != lastError) { if (error == overWriteError) displayOverWriteOccurred = 1; if (displayOverWriteOccurred) { SetCtrlAttribute (gAIpanelHandle, AI_PANEL_ERRORBOX, ATTR_TEXT_COLOR, VAL_RED); ResetTextBox (gAIpanelHandle, AI_PANEL_ERRORBOX, "Overwrite error has occurred!! Press Clear.\n(Try setting Read Mode to \"Latest\".)"); SetCtrlAttribute (gAIpanelHandle, AI_PANEL_CLEAR, ATTR_VISIBLE, 1); lastError = overWriteError; return; } if (error == 0) { SetCtrlAttribute (gAIpanelHandle, AI_PANEL_ERRORBOX, ATTR_TEXT_COLOR, VAL_BLACK); } else { SetCtrlAttribute (gAIpanelHandle, AI_PANEL_ERRORBOX, ATTR_TEXT_COLOR, VAL_RED); } ResetTextBox (gAIpanelHandle, AI_PANEL_ERRORBOX, GetDAQErrorString(error)); if (error == timeOutError || error == -timeOutError) { SetCtrlVal(gAIpanelHandle, AI_PANEL_ERRORBOX, "\nOperations will be slow while the timeout exists! Make sure your trigger specification is correct for your signal."); } SetCtrlAttribute (gAIpanelHandle, AI_PANEL_ERRORBOX, ATTR_FIRST_VISIBLE_LINE, 0); ProcessDrawEvents(); } lastError = error; } #ifndef AI_LOG int CVICALLBACK LogConfigCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) {return 0;} int CVICALLBACK LogCallback (int panel, int control, int event, void *callbackData, int eventData1, int eventData2) {return 0;} #endif