#include "hctr.h" #include #include #include #include #include #define DAQmxErrChk(functionCall) \ do { if( DAQmxFailed(error=(functionCall)) ) \ goto Error; } while(0); /** * This structure encapsulates the data that is private to * the implementation of the NI DAQ counter interface */ typedef struct counter_private_t { /** NIDAQ opaque task handle */ TaskHandle taskHandle; /** Actual physical counter value, as returned by NIDAQ * read function */ uInt32 count32; /** extended 64-bit counter value */ unsigned long long count64; /** NIDAQ device number of card */ int device_number; /** NI counter number on card */ int counter_number; /** true if using external sync else timer based sampling */ bool sync; /** sync line number on the card */ int sync_line_number; /** output line number on the card */ int output_line_number; /** NIDAQ opaque task handle for digital output */ TaskHandle taskHandle_dout; } COUNTER_PRIVATE; typedef struct mapping_t { int cntr_num; int sync_num; int outp_num; } MAPPING; MAPPING mapping[8] = { { 0, 37, 36 }, { 1, 33, 32 }, { 2, 29, 28 }, { 3, 25, 24 }, { 4, 21, 20 }, { 5, 17, 16 }, { 6, 13, 12 }, { 7, 9, 8 } }; int hctr_ctor(const char* device_name, pHCTR* ptr) { int error = 0; bool flag = false; char text_string[] = "dev1/ctr0"; const char *name; const char *text; *ptr = (COUNTER_PRIVATE*) malloc(sizeof(COUNTER_PRIVATE)); memset(*ptr, 0, sizeof(COUNTER_PRIVATE)); name = device_name; text = text_string; while (name && *name) { if (isspace(*name)) ++name; else if (*name >= '0' && *name <= '7') { if (flag) { (*ptr)->counter_number = *name - '0'; (*ptr)->sync_line_number = mapping[(*ptr)->counter_number].sync_num; (*ptr)->output_line_number = mapping[(*ptr)->counter_number].outp_num; } else { (*ptr)->device_number = *name - '0'; flag = true; } } else if (tolower(*name) != *text) { /* TODO error */ break; } ++name; ++text; } /*********************************************/ // Create a DAQmx task to hold the counter /*********************************************/ DAQmxErrChk (DAQmxCreateTask("",&(*ptr)->taskHandle)); /*********************************************/ // Create a DAQmx counter within the task /*********************************************/ DAQmxErrChk ( DAQmxCreateCICountEdgesChan((*ptr)->taskHandle, device_name, "", DAQmx_Val_Rising, (*ptr)->count32, DAQmx_Val_CountUp)); /*********************************************/ // Start the DAQmx task /*********************************************/ DAQmxErrChk (DAQmxStartTask((*ptr)->taskHandle)); return 0; Error: free(*ptr); *ptr = NULL; return error; } int hctr_read(pHCTR hctr, unsigned long long* value) { int error = 0; uInt32 ctr; DAQmxErrChk (DAQmxReadCounterScalarU32(hctr->taskHandle, 1.0, &ctr, NULL)); hctr->count64 += ctr - hctr->count32; hctr->count32 = ctr; *value = hctr->count64; return 0; Error: return error; } int make_dout_task(pHCTR ptr) { int error = 0; char port_range[40]; /*********************************************/ // Create a DAQmx task to hold the counter /*********************************************/ DAQmxErrChk (DAQmxCreateTask("",&ptr->taskHandle_dout)); /*********************************************/ // Create the digital channel within the task /*********************************************/ snprintf(port_range, sizeof(port_range), "DEV%d/LINE%d", ptr->device_number, ptr->counter_number); DAQmxErrChk (DAQmxCreateDOChan(ptr->taskHandle_dout, port_range, "", DAQmx_Val_ChanPerLine)); /*********************************************/ // Start the DAQmx task /*********************************************/ DAQmxErrChk (DAQmxStartTask(ptr->taskHandle_dout)); Error: return error; } int hctr_outp(pHCTR hctr, int value) { int error = 0; uInt8 data; if (value < 0) { if (hctr->taskHandle_dout != 0) { data = 0; DAQmxWriteDigitalLines(hctr->taskHandle_dout, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &data, NULL, NULL); /*********************************************/ // DAQmx Stop Code /*********************************************/ DAQmxStopTask(hctr->taskHandle_dout); DAQmxClearTask(hctr->taskHandle_dout); hctr->taskHandle_dout = 0; } return error; } if (hctr->taskHandle_dout == 0) DAQmxErrChk (make_dout_task(hctr)); if (value > 0) data = 1; else data = 0; #if 0 DAQmxErrChk ( DAQmxWriteDigitalLines(hctr->taskHandle_dout, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &data, NULL, NULL)); #else DAQmxErrChk ( DAQmxWriteDigitalScalarU32(hctr->taskHandle_dout, 1, 10.0, data, NULL)); #endif Error: return error; } void hctr_sync(pHCTR hctr, bool external) { int error = 0; char device_name[40]; if (hctr->sync != external) { hctr->sync = external; /*********************************************/ // DAQmx Stop Code /*********************************************/ DAQmxStopTask(hctr->taskHandle); DAQmxClearTask(hctr->taskHandle); /*********************************************/ // Create a DAQmx task to hold the counter /*********************************************/ DAQmxErrChk (DAQmxCreateTask("",&hctr->taskHandle)); /*********************************************/ // Create a DAQmx counter within the task /*********************************************/ hctr->count32 = 0; snprintf(device_name, sizeof(device_name), "dev%d/ctr%d", hctr->device_number, hctr->counter_number); DAQmxErrChk ( DAQmxCreateCICountEdgesChan(hctr->taskHandle, device_name, "", DAQmx_Val_Rising, hctr->count32, DAQmx_Val_CountUp)); if (external) { char str[40]; snprintf(str, sizeof(str), "dev%d/PFI%d", hctr->device_number, hctr->sync_line_number); DAQmxErrChk ( DAQmxCfgSampClkTiming(hctr->taskHandle, str, 10000, DAQmx_Val_Rising, DAQmx_Val_ContSamps, 10000)); } /*********************************************/ // Start the DAQmx task /*********************************************/ DAQmxErrChk (DAQmxStartTask(hctr->taskHandle)); } Error: return; } int hctr_dtor(pHCTR* hctr) { if( hctr && *hctr && (*hctr)->taskHandle!=0 ) { /*********************************************/ // DAQmx Stop Code /*********************************************/ DAQmxStopTask((*hctr)->taskHandle); DAQmxClearTask((*hctr)->taskHandle); } (*hctr)->taskHandle = 0; if( hctr && *hctr && (*hctr)->taskHandle_dout!=0 ) { /*********************************************/ // DAQmx Stop Code /*********************************************/ DAQmxStopTask((*hctr)->taskHandle_dout); DAQmxClearTask((*hctr)->taskHandle_dout); } (*hctr)->taskHandle_dout = 0; free (*hctr); *hctr = NULL; return 0; } bool hctr_failed(int error) { if (DAQmxFailed(error)) return true; else return false; } void hctr_errmsg(char* buff, int len) { *buff = '\0'; DAQmxGetExtendedErrorInfo(buff, len); }