/* vim: ts=8 sts=2 sw=2 cindent */ #include "hware.h" #include #include #include #include #ifndef SIMULATE_HARDWARE #define DEFAULT_DEVICE "dev1/ctr0" #ifdef REGISTER_LEVEL_PROGRAMMING #define DEVICE_ID_NUMBER "0x1310" #define DAQmxFailed(e) ((e) != 0) #define DAQmxGetExtendedErrorInfo(b, l) snprintf(b, l, "BAD") #include #include typedef unsigned long uInt32; /** * This structure contains the data for the PCI-6602 card */ typedef struct card_t { iBus* bus; tAddressSpace Bar1; tAddressSpace Bar2; tTIO *tio_1; tTIO *tio_2; unsigned char dio_mask; unsigned char dev_mask; } CARD; #else #include #define DAQmxErrChk(functionCall) \ do { if( DAQmxFailed(error=(functionCall)) ) \ goto Error; } while(0) #endif /** * This structure encapsulates the data that is private to * the implementation of the device */ typedef struct device_private_t { /** extended 64-bit counter value */ unsigned long long count64; /** NIDAQ device number of card */ int card_number; /** NI channel number on card */ int channel_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; /** Actual physical counter value, as returned by read function */ uInt32 count32; #ifdef REGISTER_LEVEL_PROGRAMMING CARD* card; #else /** NIDAQ opaque task handle */ TaskHandle taskHandle; /** NIDAQ opaque task handle for digital output */ TaskHandle taskHandle_dout; #endif } DEVICE_PRIVATE; #ifdef REGISTER_LEVEL_PROGRAMMING static bool initPCI(pHWARE ptr, const char *name); static void initCard(pHWARE ptr); static void initChan(pHWARE ptr); static CARD* card[10]; #else typedef struct mapping_t { int cntr_num; int sync_num; int outp_num; } MAPPING; static 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 } }; #endif int hware_ctor(const char* device_name, pHWARE* ptr) { pHWARE hware = NULL; #ifdef REGISTER_LEVEL_PROGRAMMING CARD* pci = NULL; #endif int error = 0; bool flag = false; char text_string[] = DEFAULT_DEVICE; const char *name; const char *text; hware = (DEVICE_PRIVATE*) malloc(sizeof(DEVICE_PRIVATE)); *ptr = hware; memset(hware, 0, sizeof(DEVICE_PRIVATE)); name = device_name; text = text_string; while (name && *name) { if (isspace(*name)) ++name; else if (*name >= '0' && *name <= '9') { if (flag) { hware->channel_number = *name - '0'; } else { hware->card_number = *name - '0'; flag = true; } } else if (tolower(*name) != *text) { /* TODO error */ printf("Device name error: %s (%d,%d)\n", device_name, hware->channel_number, hware->card_number); break; } ++name; ++text; } #ifdef REGISTER_LEVEL_PROGRAMMING if (card[hware->card_number] == NULL) { char local_name[40] = "PXI6::1::INSTR"; FILE* fd = fopen("/proc/nirlpk/lsdaq", "r"); if (fd) { bool found = false; int count = 0; char line[100]; while (fgets(line, 100, fd)) { if (strstr(line, DEVICE_ID_NUMBER)) { ++count; name = strstr(line, "PXI"); if (name && count == hware->card_number) { found = true; strcpy(local_name, name); break; } } if (!found) { // TODO error } } fclose(fd); } card[hware->card_number] = (CARD*) malloc(sizeof(CARD)); memset(card[hware->card_number], 0, sizeof(CARD)); pci = card[hware->card_number]; hware->card = pci; if(!initPCI(hware, local_name)) { printf("Error accessing the PCI device \"%s\". Exiting.\n", local_name); error = 1; goto Error; } initCard(hware); } else { pci = card[hware->card_number]; hware->card = pci; } // Mark the counter on this card as in-use if (pci->dev_mask & (1 << hware->channel_number)) { // TODO error } pci->dev_mask |= 1 << hware->channel_number; initChan(hware); #else do { char local_name[40]; hware->sync_line_number = mapping[hware->channel_number].sync_num; hware->output_line_number = mapping[hware->channel_number].outp_num; /*********************************************/ // Create a DAQmx task /*********************************************/ DAQmxErrChk (DAQmxCreateTask("",&hware->taskHandle)); DAQmxErrChk (DAQmxCreateTask("",&hware->taskHandle_dout)); /*********************************************/ // Create a DAQmx device within the task /*********************************************/ DAQmxErrChk ( DAQmxCreateCICountEdgesChan(hware->taskHandle, device_name, "", DAQmx_Val_Rising, hware->count32, DAQmx_Val_CountUp)); /*********************************************/ // Create the digital output channel within the task /*********************************************/ snprintf(local_name, sizeof(local_name), "dev%d/line%d", hware->card_number, hware->channel_number); DAQmxErrChk ( DAQmxCreateDOChan(hware->taskHandle_dout, local_name, "", DAQmx_Val_ChanPerLine)); /*********************************************/ // Start the DAQmx task /*********************************************/ DAQmxErrChk (DAQmxStartTask(hware->taskHandle)); DAQmxErrChk (DAQmxStartTask(hware->taskHandle_dout)); hware_outp(hware, 0); } while (0); #endif return 0; Error: free(hware); *ptr = NULL; return error; } int hware_read(pHWARE hware, unsigned long long* value) { int error = 0; uInt32 counterValue1; *value = hware->count64; #ifdef REGISTER_LEVEL_PROGRAMMING uInt32 counterValue2; CARD* pci = hware->card; //read counter value //Use this method to read the value of an armed counter //during non-buffered counting. Since the value of the counter may //change during the read, we make sure that the value is stable. switch (hware->channel_number) { case 0: counterValue1 = pci->tio_1->G0_Save_Registers.readRegister(); counterValue2 = pci->tio_1->G0_Save_Registers.readRegister(); if (counterValue1 != counterValue2) counterValue1 = pci->tio_1->G0_Save_Registers.readRegister(); break; case 1: counterValue1 = pci->tio_1->G1_Save_Registers.readRegister(); counterValue2 = pci->tio_1->G1_Save_Registers.readRegister(); if (counterValue1 != counterValue2) counterValue1 = pci->tio_1->G1_Save_Registers.readRegister(); break; case 2: counterValue1 = pci->tio_1->G2_Save_Registers.readRegister(); counterValue2 = pci->tio_1->G2_Save_Registers.readRegister(); if (counterValue1 != counterValue2) counterValue1 = pci->tio_1->G2_Save_Registers.readRegister(); break; case 3: counterValue1 = pci->tio_1->G3_Save_Registers.readRegister(); counterValue2 = pci->tio_1->G3_Save_Registers.readRegister(); if (counterValue1 != counterValue2) counterValue1 = pci->tio_1->G3_Save_Registers.readRegister(); break; case 4: counterValue1 = pci->tio_2->G0_Save_Registers.readRegister(); counterValue2 = pci->tio_2->G0_Save_Registers.readRegister(); if (counterValue1 != counterValue2) counterValue1 = pci->tio_2->G0_Save_Registers.readRegister(); break; case 5: counterValue1 = pci->tio_2->G1_Save_Registers.readRegister(); counterValue2 = pci->tio_2->G1_Save_Registers.readRegister(); if (counterValue1 != counterValue2) counterValue1 = pci->tio_2->G1_Save_Registers.readRegister(); break; case 6: counterValue1 = pci->tio_2->G2_Save_Registers.readRegister(); counterValue2 = pci->tio_2->G2_Save_Registers.readRegister(); if (counterValue1 != counterValue2) counterValue1 = pci->tio_2->G2_Save_Registers.readRegister(); break; case 7: counterValue1 = pci->tio_2->G3_Save_Registers.readRegister(); counterValue2 = pci->tio_2->G3_Save_Registers.readRegister(); if (counterValue1 != counterValue2) counterValue1 = pci->tio_2->G3_Save_Registers.readRegister(); break; } hware->count64 += counterValue1 - hware->count32; hware->count32 = counterValue1; *value = hware->count64; #else /*********************************************/ // DAQmx Read Code /*********************************************/ DAQmxErrChk (DAQmxReadCounterScalarU32(hware->taskHandle, 1.0, &counterValue1, NULL)); hware->count64 += counterValue1 - hware->count32; hware->count32 = counterValue1; *value = hware->count64; Error: #endif return error; } /* hware_read */ /* * Select the source */ int hware_source(pHWARE hware, int value) { int error = 0; #ifdef REGISTER_LEVEL_PROGRAMMING CARD* pci = hware->card; int src = 1; if (value == 3) //set source to internal time base 3, the 80Mhz internal clock src = 30; else if (value == 2) //set source to internal time base 2, the l00Khz internal clock src = 18; else if (value == 1) //set source to internal time base 1, the 20Mhz internal clock src = 0; else //set source to external default source pin src = 1; switch (hware->channel_number) { case 0: pci->tio_1->G0_Input_Select_Register.writeG0_Source_Select(src); break; case 1: pci->tio_1->G1_Input_Select_Register.writeG1_Source_Select(src); break; case 2: pci->tio_1->G2_Input_Select_Register.writeG2_Source_Select(src); break; case 3: pci->tio_1->G3_Input_Select_Register.writeG3_Source_Select(src); break; case 4: pci->tio_2->G0_Input_Select_Register.writeG0_Source_Select(src); break; case 5: pci->tio_2->G1_Input_Select_Register.writeG1_Source_Select(src); break; case 6: pci->tio_2->G2_Input_Select_Register.writeG2_Source_Select(src); break; case 7: pci->tio_2->G3_Input_Select_Register.writeG3_Source_Select(src); break; } #else // TODO // DAQmxGetDevCIPhysicalChans // DAQmxSetCICountEdgesTerm //Error: #endif return error; } /* * Select the filter */ int hware_filter(pHWARE hware, int value) { int error = 0; #ifdef REGISTER_LEVEL_PROGRAMMING CARD* pci = hware->card; int src = 0; if (value > 0 && value < 7) src = value; switch (hware->channel_number) { case 0: pci->tio_1->IO_Pin_38_39_Configuration_Register.writeIO_Filter_39_Select(src); break; case 1: pci->tio_1->IO_Pin_34_35_Configuration_Register.writeIO_Filter_35_Select(src); break; case 2: pci->tio_1->IO_Pin_30_31_Configuration_Register.writeIO_Filter_31_Select(src); break; case 3: pci->tio_1->IO_Pin_26_27_Configuration_Register.writeIO_Filter_27_Select(src); break; case 4: pci->tio_2->IO_Pin_22_23_Configuration_Register.writeIO_Filter_23_Select(src); break; case 5: pci->tio_2->IO_Pin_18_19_Configuration_Register.writeIO_Filter_19_Select(src); break; case 6: pci->tio_2->IO_Pin_14_15_Configuration_Register.writeIO_Filter_15_Select(src); break; case 7: pci->tio_2->IO_Pin_10_11_Configuration_Register.writeIO_Filter_11_Select(src); break; } #else // TODO // DAQmxGetDevCIPhysicalChans // DAQmxSetCICountEdgesTerm //Error: #endif return error; } /* * Set the output line corresponding to the counter */ int hware_outp(pHWARE hware, int value) { int error = 0; #ifdef REGISTER_LEVEL_PROGRAMMING CARD* pci = hware->card; u16 data; if (value < 0) { // set the disabled line to input value = 0; pci->dio_mask &= ~(1 << hware->channel_number); pci->tio_1->DIO_Control_Register.writeDIO_Pins_Dir(pci->dio_mask); } else { pci->dio_mask |= 1 << hware->channel_number; pci->tio_1->DIO_Control_Register.writeDIO_Pins_Dir(pci->dio_mask); data = pci->tio_1->DIO_Output_Register.readDIO_Parallel_Data_Out(); printf("data %04x", data); if (value > 0) data |= 1 << hware->channel_number; else data &= ~(1 << hware->channel_number); pci->tio_1->DIO_Output_Register.writeDIO_Parallel_Data_Out(data); printf(" => %04x", data); data = pci->tio_1->DIO_Output_Register.readDIO_Parallel_Data_Out(); printf(" => %04x\n", data); } #else uInt8 data; if (value < 0) { // set the disabled line to logic low data = 0; DAQmxWriteDigitalLines(hware->taskHandle_dout, 1, 1, 10.0, DAQmx_Val_GroupByChannel, &data, NULL, NULL); } else { if (value > 0) data = 1; else data = 0; DAQmxErrChk ( DAQmxWriteDigitalScalarU32(hware->taskHandle_dout, 1, 10.0, data, NULL)); } Error: #endif return error; } /* * Set up to read the counter synchronized to an external signal */ void hware_sync(pHWARE hware, bool external) { #if REGISTER_LEVEL_PROGRAMMING //CARD* pci = hware->card; // TODO RLP #else int error = 0; char device_name[40]; if (hware->sync != external) { hware->sync = external; /*********************************************/ // DAQmx Stop Code /*********************************************/ DAQmxStopTask(hware->taskHandle); DAQmxClearTask(hware->taskHandle); /*********************************************/ // Create a DAQmx task to hold the counter /*********************************************/ DAQmxErrChk (DAQmxCreateTask("",&hware->taskHandle)); /*********************************************/ // Create a DAQmx counter within the task /*********************************************/ hware->count32 = 0; snprintf(device_name, sizeof(device_name), "dev%d/ctr%d", hware->card_number, hware->channel_number); DAQmxErrChk ( DAQmxCreateCICountEdgesChan(hware->taskHandle, device_name, "", DAQmx_Val_Rising, hware->count32, DAQmx_Val_CountUp)); if (external) { char str[40]; snprintf(str, sizeof(str), "dev%d/PFI%d", hware->card_number, hware->sync_line_number); DAQmxErrChk ( DAQmxCfgSampClkTiming(hware->taskHandle, str, 10000, DAQmx_Val_Rising, DAQmx_Val_ContSamps, 10000)); } /*********************************************/ // Start the DAQmx task /*********************************************/ DAQmxErrChk (DAQmxStartTask(hware->taskHandle)); } Error: #endif return; } /* * Shut down the channel */ int hware_dtor(pHWARE* ptr) { if (ptr && *ptr) { pHWARE hware = *ptr; #ifdef REGISTER_LEVEL_PROGRAMMING CARD* pci = hware->card; switch (hware->channel_number) { case 0: pci->tio_1->G0_Command_Register.writeG0_Disarm(1); break; case 1: pci->tio_1->G1_Command_Register.writeG1_Disarm(1); break; case 2: pci->tio_1->G2_Command_Register.writeG2_Disarm(1); break; case 3: pci->tio_1->G3_Command_Register.writeG3_Disarm(1); break; case 4: pci->tio_2->G0_Command_Register.writeG0_Disarm(1); break; case 5: pci->tio_2->G1_Command_Register.writeG1_Disarm(1); break; case 6: pci->tio_2->G2_Command_Register.writeG2_Disarm(1); break; case 7: pci->tio_2->G3_Command_Register.writeG3_Disarm(1); break; } pci->dev_mask &= ~(1 << hware->channel_number); if (pci->dev_mask == 0) { delete pci->tio_1; delete pci->tio_2; pci->bus->destroyAddressSpace(pci->Bar1); pci->bus->destroyAddressSpace(pci->Bar2); releaseBoard(pci->bus); card[hware->card_number] = NULL; free(pci); } #else if (hware->taskHandle != 0) { /*********************************************/ // DAQmx Stop Code /*********************************************/ DAQmxStopTask(hware->taskHandle); DAQmxClearTask(hware->taskHandle); hware->taskHandle = 0; } if (hware->taskHandle_dout != 0) { /*********************************************/ // DAQmx Stop Code /*********************************************/ DAQmxStopTask(hware->taskHandle_dout); DAQmxClearTask(hware->taskHandle_dout); hware->taskHandle_dout = 0; } #endif /* release the storage */ free(hware); *ptr = NULL; } return 0; } bool hware_failed(int error) { if (DAQmxFailed(error)) return true; else return false; } void hware_errmsg(char* buff, int len) { *buff = '\0'; DAQmxGetExtendedErrorInfo(buff, len); } #ifdef REGISTER_LEVEL_PROGRAMMING // //Tell the MITE to link the BAR1 address to the DAQ Board //You must initialize the MITE before you write to the rest of the PCI board void initMite(iBus *bus) { tAddressSpace Bar0; u32 physicalBar1; //Skip MITE initialization for PCMCIA boards //(which do not have a MITE DMA controller) if(!bus->get(kIsPciPxiBus,0)) return; Bar0 = bus->createAddressSpace(kPCI_BAR0); //Get the physical address of the DAQ board physicalBar1 = bus->get(kBusAddressPhysical,kPCI_BAR1); // ***** 6602/6608 specific MITE initialization ***** // Hit the IO Window Base/Size Register 1 (IOWBSR1) in the MITE. We set the // address, enable the window and set the size of the window: Bar0.write32(0xC4, (physicalBar1 & 0xffffff00L) | 0x8C); // Write to the IO Window Control Register 1 (IOWCR1) to make the IO window // go to RAM memory space instead of the config space Bar0.write32(0xF4, 0); // ***** End of 6602/6608 specific code ***** bus->destroyAddressSpace(Bar0); } bool initPCI(pHWARE hware, const char* name) { CARD* pci = hware->card; pci->bus = acquireBoard((tChar*) name); if(pci->bus == NULL) { return false; } //Intitialise Mite Chip. initMite(pci->bus); return true; } void initCard(pHWARE hware) { CARD* pci = hware->card; pci->Bar1 = pci->bus->createAddressSpace(kPCI_BAR1); pci->Bar2 = pci->bus->createAddressSpace(kPCI_BAR1); pci->tio_1 = new tTIO(pci->Bar1); pci->tio_2 = new tTIO(pci->Bar2); pci->tio_2->setAddressOffset(0x800); // // Set all counter outputs to 'input' so we don't accidentally double drive an IO pin pci->tio_1->IO_Pin_8_9_Configuration_Register.writeIO_Pin_8_Select(0); //0='input' pci->tio_1->IO_Pin_12_13_Configuration_Register.writeIO_Pin_12_Select(0); //0='input' pci->tio_1->IO_Pin_16_17_Configuration_Register.writeIO_Pin_16_Select(0); //0='input' pci->tio_1->IO_Pin_20_21_Configuration_Register.writeIO_Pin_20_Select(0); //0='input' pci->tio_1->IO_Pin_24_25_Configuration_Register.writeIO_Pin_24_Select(0); //0='input' pci->tio_1->IO_Pin_28_29_Configuration_Register.writeIO_Pin_28_Select(0); //0='input' pci->tio_1->IO_Pin_32_33_Configuration_Register.writeIO_Pin_32_Select(0); //0='input' pci->tio_1->IO_Pin_36_37_Configuration_Register.writeIO_Pin_36_Select(0); //0='input' pci->tio_2->IO_Pin_8_9_Configuration_Register.writeIO_Pin_8_Select(0); //0='input' pci->tio_2->IO_Pin_12_13_Configuration_Register.writeIO_Pin_12_Select(0); //0='input' pci->tio_2->IO_Pin_16_17_Configuration_Register.writeIO_Pin_16_Select(0); //0='input' pci->tio_2->IO_Pin_20_21_Configuration_Register.writeIO_Pin_20_Select(0); //0='input' pci->tio_2->IO_Pin_24_25_Configuration_Register.writeIO_Pin_24_Select(0); //0='input' pci->tio_2->IO_Pin_28_29_Configuration_Register.writeIO_Pin_28_Select(0); //0='input' pci->tio_2->IO_Pin_32_33_Configuration_Register.writeIO_Pin_32_Select(0); //0='input' pci->tio_2->IO_Pin_36_37_Configuration_Register.writeIO_Pin_36_Select(0); //0='input' //Bind the first TIO to counters 0-3 on the IO connector, and //bind the second TIO to counters 4-7 pci->tio_1->Clock_Configuration_Register.writeCntr_Swap(0); pci->tio_2->Clock_Configuration_Register.writeCntr_Swap(1); } void initChan(pHWARE hware) { CARD* pci = hware->card; /* * Set up the channel object */ switch (hware->channel_number) { case 0: //Disarm pci->tio_1->G0_Command_Register.writeG0_Disarm(1); //load initial value of zero pci->tio_1->G0_Load_A_Registers.writeG0_Load_A(0x00000000); pci->tio_1->G0_Command_Register.writeG0_Load(1); //set source to external default source pin pci->tio_1->G0_Input_Select_Register.writeG0_Source_Select(1); //set gate to no gate pci->tio_1->G0_Input_Select_Register.writeG0_Gate_Select(30); pci->tio_1->G0_Mode_Register.writeG0_Gate_Polarity(1); pci->tio_1->G0_Mode_Register.writeG0_Trigger_Mode_For_Edge_Gate(3); //set counting direction to up pci->tio_1->G0_Command_Register.writeG0_Up_Down(1); //arm counter pci->tio_1->G0_Command_Register.writeG0_Arm(1); break; case 1: //Disarm pci->tio_1->G1_Command_Register.writeG1_Disarm(1); //load initial value of zero pci->tio_1->G1_Load_A_Registers.writeG1_Load_A(0x00000000); pci->tio_1->G1_Command_Register.writeG1_Load(1); //set source to external default source pin pci->tio_1->G1_Input_Select_Register.writeG1_Source_Select(1); //set gate to no gate pci->tio_1->G1_Input_Select_Register.writeG1_Gate_Select(30); pci->tio_1->G1_Mode_Register.writeG1_Gate_Polarity(1); pci->tio_1->G1_Mode_Register.writeG1_Trigger_Mode_For_Edge_Gate(3); //set counting direction to up pci->tio_1->G1_Command_Register.writeG1_Up_Down(1); //arm counter pci->tio_1->G1_Command_Register.writeG1_Arm(1); break; case 2: //Disarm pci->tio_1->G2_Command_Register.writeG2_Disarm(1); //load initial value of zero pci->tio_1->G2_Load_A_Registers.writeG2_Load_A(0x00000000); pci->tio_1->G2_Command_Register.writeG2_Load(1); //set source to external default source pin pci->tio_1->G2_Input_Select_Register.writeG2_Source_Select(1); //set gate to no gate pci->tio_1->G2_Input_Select_Register.writeG2_Gate_Select(30); pci->tio_1->G2_Mode_Register.writeG2_Gate_Polarity(1); pci->tio_1->G2_Mode_Register.writeG2_Trigger_Mode_For_Edge_Gate(3); //set counting direction to up pci->tio_1->G2_Command_Register.writeG2_Up_Down(1); //arm counter pci->tio_1->G2_Command_Register.writeG2_Arm(1); break; case 3: //Disarm pci->tio_1->G3_Command_Register.writeG3_Disarm(1); //load initial value of zero pci->tio_1->G3_Load_A_Registers.writeG3_Load_A(0x00000000); pci->tio_1->G3_Command_Register.writeG3_Load(1); //set source to external default source pin pci->tio_1->G3_Input_Select_Register.writeG3_Source_Select(1); //set gate to no gate pci->tio_1->G3_Input_Select_Register.writeG3_Gate_Select(30); pci->tio_1->G3_Mode_Register.writeG3_Gate_Polarity(1); pci->tio_1->G3_Mode_Register.writeG3_Trigger_Mode_For_Edge_Gate(3); //set counting direction to up pci->tio_1->G3_Command_Register.writeG3_Up_Down(1); //arm counter pci->tio_1->G3_Command_Register.writeG3_Arm(1); break; case 4: //Disarm pci->tio_2->G0_Command_Register.writeG0_Disarm(1); //load initial value of zero pci->tio_2->G0_Load_A_Registers.writeG0_Load_A(0x00000000); pci->tio_2->G0_Command_Register.writeG0_Load(1); //set source to external default source pin pci->tio_2->G0_Input_Select_Register.writeG0_Source_Select(1); //set gate to no gate pci->tio_2->G0_Input_Select_Register.writeG0_Gate_Select(30); pci->tio_2->G0_Mode_Register.writeG0_Gate_Polarity(1); pci->tio_2->G0_Mode_Register.writeG0_Trigger_Mode_For_Edge_Gate(3); //set counting direction to up pci->tio_2->G0_Command_Register.writeG0_Up_Down(1); //arm counter pci->tio_2->G0_Command_Register.writeG0_Arm(1); break; case 5: //Disarm pci->tio_2->G1_Command_Register.writeG1_Disarm(1); //load initial value of zero pci->tio_2->G1_Load_A_Registers.writeG1_Load_A(0x00000000); pci->tio_2->G1_Command_Register.writeG1_Load(1); //set source to external default source pin pci->tio_2->G1_Input_Select_Register.writeG1_Source_Select(1); //set gate to no gate pci->tio_2->G1_Input_Select_Register.writeG1_Gate_Select(30); pci->tio_2->G1_Mode_Register.writeG1_Gate_Polarity(1); pci->tio_2->G1_Mode_Register.writeG1_Trigger_Mode_For_Edge_Gate(3); //set counting direction to up pci->tio_2->G1_Command_Register.writeG1_Up_Down(1); //arm counter pci->tio_2->G1_Command_Register.writeG1_Arm(1); break; case 6: //Disarm pci->tio_2->G2_Command_Register.writeG2_Disarm(1); //load initial value of zero pci->tio_2->G2_Load_A_Registers.writeG2_Load_A(0x00000000); pci->tio_2->G2_Command_Register.writeG2_Load(1); //set source to external default source pin pci->tio_2->G2_Input_Select_Register.writeG2_Source_Select(1); //set gate to no gate pci->tio_2->G2_Input_Select_Register.writeG2_Gate_Select(30); pci->tio_2->G2_Mode_Register.writeG2_Gate_Polarity(1); pci->tio_2->G2_Mode_Register.writeG2_Trigger_Mode_For_Edge_Gate(3); //set counting direction to up pci->tio_2->G2_Command_Register.writeG2_Up_Down(1); //arm counter pci->tio_2->G2_Command_Register.writeG2_Arm(1); break; case 7: //Disarm pci->tio_2->G3_Command_Register.writeG3_Disarm(1); //load initial value of zero pci->tio_2->G3_Load_A_Registers.writeG3_Load_A(0x00000000); pci->tio_2->G3_Command_Register.writeG3_Load(1); //set source to external default source pin pci->tio_2->G3_Input_Select_Register.writeG3_Source_Select(1); //set gate to no gate pci->tio_2->G3_Input_Select_Register.writeG3_Gate_Select(30); pci->tio_2->G3_Mode_Register.writeG3_Gate_Polarity(1); pci->tio_2->G3_Mode_Register.writeG3_Trigger_Mode_For_Edge_Gate(3); //set counting direction to up pci->tio_2->G3_Command_Register.writeG3_Up_Down(1); //arm counter pci->tio_2->G3_Command_Register.writeG3_Arm(1); break; } } #else #endif #else /* SIMULATE_HARDWARE */ #include typedef struct device_private_t { /** extended 64-bit counter value */ unsigned long long count64; /** count rate to be simulated */ int source; /** time that count64 was last updated */ struct timeval prev_time; /** time of most recent read operation */ struct timeval curr_time; } DEVICE_PRIVATE; int hware_ctor(const char* device_name, pHWARE* ptr) { pHWARE hware = NULL; hware = (DEVICE_PRIVATE*) malloc(sizeof(DEVICE_PRIVATE)); *ptr = hware; memset(hware, 0, sizeof(DEVICE_PRIVATE)); /* set initital conditions */ hware->source = 1000; /* initial count rate */ hware->count64 = 0; /* initial counter value */ gettimeofday(&hware->curr_time, NULL); /* current time */ hware->prev_time = hware->curr_time; /* update time */ return 0; } int hware_read(pHWARE hware, unsigned long long* value) { double delta_time; unsigned long long delta_count = 0; unsigned long long total_count = 0; /* calculate time since count64 update in microseconds */ gettimeofday(&hware->curr_time, NULL); delta_time = (hware->curr_time.tv_sec + 1e-6 * hware->curr_time.tv_usec) - (hware->prev_time.tv_sec + 1e-6 * hware->prev_time.tv_usec); /* calculate counts since then */ delta_count = (long long)(0.5 + delta_time * hware->source); /* calculate the new total counts */ total_count = hware->count64 + delta_count; /* periodically update count64 */ if (delta_time > 60) { hware->count64 = total_count; hware->prev_time = hware->curr_time; } /* return the total count */ *value = total_count; return 0; } /* * Change the count rate */ int hware_source(pHWARE hware, int value) { /* calculate the new count rate */ int new_source; switch (value) { case 0: new_source = 10000; break; case 1: new_source = 20000000; break; case 2: new_source = 100000; break; case 3: new_source = 80000000; break; default: new_source = abs(value); break; } /* only do this if it has changed */ if (new_source != hware->source) { /* save the current count where the slope changes */ hware_read(hware, &hware->count64); /* save the current time where the slope changes */ hware->prev_time = hware->curr_time; /* save the new slope */ hware->source = new_source; } return 0; } int hware_filter(pHWARE hware, int value) { /* nothing to do */ return 0; } int hware_outp(pHWARE hware, int value) { /* nothing to do */ return 0; } void hware_sync(pHWARE hware, bool external) { /* nothing to do */ } int hware_dtor(pHWARE* ptr) { if (ptr && *ptr) { /* release the storage */ free(*ptr); *ptr = NULL; } return 0; } bool hware_failed(int error) { return false; } void hware_errmsg(char* buff, int len) { if (buff) strncpy(buff, "Simulated error message", len); } #endif