diff --git a/site_ansto/hardsup/Monitor/hware.c b/site_ansto/hardsup/Monitor/hware.c new file mode 100644 index 00000000..2efcf674 --- /dev/null +++ b/site_ansto/hardsup/Monitor/hware.c @@ -0,0 +1,838 @@ +/* vim: ts=8 sts=2 sw=2 cindent + */ +#include "hware.h" + +#include +#include +#include +#include + +#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; + +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 } +}; + +#ifdef REGISTER_LEVEL_PROGRAMMING +static void initMite(iBus *bus); + +static CARD* card[10]; +#else +static int make_dout_task(pHWARE ptr); +#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 <= '7') + { + if (flag) + { + hware->channel_number = *name - '0'; + hware->sync_line_number = mapping[hware->channel_number].sync_num; + hware->output_line_number = mapping[hware->channel_number].outp_num; + } + 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; + + pci->bus = acquireBoard((tChar*) local_name /* "PXI6::1::INSTR" */); + + if(pci->bus == NULL) + { + printf("Error accessing the PCI device \"%s\". Exiting.\n", + local_name); + error = 1; + goto Error; + } + + //Intitialise Mite Chip. + + initMite(pci->bus); + + 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); + } + 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; + + /* + * Set up the counter 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 + /*********************************************/ + // Create a DAQmx task + /*********************************************/ + DAQmxErrChk (DAQmxCreateTask("",&hware->taskHandle)); + + /*********************************************/ + // Create a DAQmx device within the task + /*********************************************/ + DAQmxErrChk ( + DAQmxCreateCICountEdgesChan(hware->taskHandle, + device_name, + "", + DAQmx_Val_Rising, + hware->count32, + DAQmx_Val_CountUp)); + + /*********************************************/ + // Start the DAQmx task + /*********************************************/ + DAQmxErrChk (DAQmxStartTask(hware->taskHandle)); +#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; +} + +/* + * 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 + if (hware->taskHandle_dout != 0) { + data = 0; + DAQmxWriteDigitalLines(hware->taskHandle_dout, + 1, + 1, + 10.0, + DAQmx_Val_GroupByChannel, + &data, + NULL, + NULL); + /*********************************************/ + // DAQmx Stop Code + /*********************************************/ + DAQmxStopTask(hware->taskHandle_dout); + DAQmxClearTask(hware->taskHandle_dout); + hware->taskHandle_dout = 0; + } + } + else + { + if (hware->taskHandle_dout == 0) + DAQmxErrChk (make_dout_task(hware)); + 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 +#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); +} +#else +int make_dout_task(pHWARE 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->card_number, ptr->channel_number); + DAQmxErrChk (DAQmxCreateDOChan(ptr->taskHandle_dout, + port_range, + "", + DAQmx_Val_ChanPerLine)); + + /*********************************************/ + // Start the DAQmx task + /*********************************************/ + DAQmxErrChk (DAQmxStartTask(ptr->taskHandle_dout)); + return error; + +Error: + return error; +} +#endif diff --git a/site_ansto/hardsup/Monitor/hware.h b/site_ansto/hardsup/Monitor/hware.h new file mode 100644 index 00000000..8f7111f3 --- /dev/null +++ b/site_ansto/hardsup/Monitor/hware.h @@ -0,0 +1,105 @@ +/* + * This is an encapsulation of a National Instruments counter. + * + * It presents a simple 64-bit counter abstraction. When the counter is + * created, it commences counting at zero until it is destroyed. + * + * The counter can be read and returns a 64-bit unsigned value. + */ +#ifndef _HWARE_H_ +#define _HWARE_H_ + +#ifdef __cplusplus +#else +#include +#endif + +struct device_private_t; +typedef struct device_private_t* pHWARE; + +/** + * Create a 64-bit counter and start it counting + * + * \param card_name the name of the device (e.g. "dev1/ctr0") + * \param ptr address of pointer to opaque private data structure + * + * \return + * 0 OK + * !0 Error + */ +int hware_ctor(const char* card_name, pHWARE* ptr); + +/** + * Read the value of the 64-bit counter + * + * \param hware pointer to opaque private data structure + * \param value address of unsigned 64-bit value to receive the output + * + * \return + * 0 OK + * !0 Error + */ +int hware_read(pHWARE hware, unsigned long long* value); + +/** + * Select the source + * + * \param value source selector + * 3 Timebase 3 (80Mhz on PCI-6602) + * 2 Timebase 2 (100Khz on PCI-6602) + * 1 Timebase 1 (20Mhz on PCI-6602) + * else default external pin + */ +int hware_source(pHWARE hware, int value); + +/** + * Enables external output on designated DIO line + * + * \param hware pointer to opaque private data structure + * \param value to be written to the associated line + * < 0 disconnect + * = 0 logic low + * > 0 logic high + */ +int hware_outp(pHWARE hware, int value); + +/** + * Enables external sync on designated (up/down) line + * + * \param hware pointer to opaque private data structure + * \param external true for external sync, false for internal + */ +void hware_sync(pHWARE hware, bool external); + +/** + * Destroy the 64-bit counter + * + * \param ptr address of pointer to opaque private data structure + * + * \return + * 0 OK + * !0 Error + */ +int hware_dtor(pHWARE* hware); + +/** + * Tests returned error value to see if it represents failure + * + * \param error a value returned from another hware function + * + * \return + * true the error was a failure + * false the error was not a failure (warning) + */ +bool hware_failed(int error); + +/** + * Retrieves a textual representation of the most recent error + * + * \param buff a pointer to the buffer to receive the text + * \param len the length of the provided buffer + */ +void hware_errmsg(char* buff, int len); + +#endif +