//****************************************************************************** //Constants //****************************************************************************** #define NMAX_V812_MODULES 10 //maximum 65535, probably more than enough... #define V812_CHANNELS 16 #include "v812.h" //****************************************************************************** //Type definitions //****************************************************************************** //****************************************************************************** //Global Variables //****************************************************************************** v812_module_t v812_modules[NMAX_V812_MODULES]; //****************************************************************************** //Function Definitions //****************************************************************************** VME_ErrorCode_t V812_Open(void) { u_int tmp_virtual_address, tmp_base_address; u_short i=0; VME_ErrorCode_t error_code; VME_MasterMap_t master_map; master_map.vmebus_address = 0x00010000; master_map.window_size = 0x1000; master_map.address_modifier = VME_A24; master_map.options = 0; for(i=0; i=NMAX_V812_MODULES) { printf("Reading input file v812_base.dat: More addresses found than memory space provided.\nIncrease NMAX_V812_MODULES in v812.h and v812.c.\n"); break; } master_map.vmebus_address = tmp_base_address; if(error_code = VME_MasterMap(&master_map,&v812_modules[i].master_mapping)) { VME_ErrorPrint(error_code); return error_code; } if(error_code = VME_MasterMapVirtualAddress(v812_modules[i].master_mapping,&tmp_virtual_address)) { VME_ErrorPrint(error_code); return error_code; } v812_modules[i].registers = (v812_registers_t *) tmp_virtual_address; if(v812_modules[i].registers->manufacturer_type==0x0851) { //printf("v812-module %i found at address 0x%08x:\n\tMaster mapping: %i\n\tVirtual address: 0x%08x\n\n",i+1,tmp_base_address,v812_modules[i].master_mapping,v812_modules[i].registers); v812_modules[i].present = 1; } else { printf("Module %i at address 0x%08x is not of type v812, or module not found. Please check the v812_base.dat-file.\n\n",i+1,tmp_base_address); v812_modules[i].present = 0; if(error_code = VME_MasterUnmap(v812_modules[i].master_mapping)) { VME_ErrorPrint(error_code); return error_code; } } i++; } fclose(datfile); } else { printf("File v812_base.dat containing the base addresses of the v812-modules not found.\n"); error_code = VME_FILE; return error_code; } return VME_SUCCESS; } //****************************************************************************** int V812_Set_Threshold(short module, short channel, short threshold) { //return values //0: threshold set successful //1: module out of range or not present //2: channel number out of range //3: threshold out of range (threshold in mV between -1 mV and -255 mV) if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; } if(!((channel>=0) && (channel<=15))) { return 2; } if(!((threshold>=1) && (channel<=255))) { return 3; } v812_modules[module-1].registers->threshold_ch[channel] = threshold; return 0; /* comment on little/big endian: the Intel architecture uses little Endian coding, whereas the VME-Standard uses big Endian (to my knowledge). Nonetheless the thresholds can be written directly to the module memory since the thresholds are saved as 8 bit words located at the adress of the short integer (according to the Technical Information Manual MOD. V 812 Series, p 16). */ } //****************************************************************************** int V812_Set_Pattern_Inhibit(short module, char channels[16]) { //return values //0: pattern of inhibit written successfully //1: module out of range or not present if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; } //create the pattern of inhibit u_short pattern = 0; int i; for(i=0; i<16; i++) { if(channels[i]!=0) { switch(i) { case 0: pattern |= 0x0001; break; case 1: pattern |= 0x0002; break; case 2: pattern |= 0x0004; break; case 3: pattern |= 0x0008; break; case 4: pattern |= 0x0010; break; case 5: pattern |= 0x0020; break; case 6: pattern |= 0x0040; break; case 7: pattern |= 0x0080; break; case 8: pattern |= 0x0100; break; case 9: pattern |= 0x0200; break; case 10: pattern |= 0x0400; break; case 11: pattern |= 0x0800; break; case 12: pattern |= 0x1000; break; case 13: pattern |= 0x2000; break; case 14: pattern |= 0x4000; break; case 15: pattern |= 0x8000; break; } } } v812_modules[module-1].registers->pattern_inhibit = pattern; return 0; } int V812_Set_Pattern_Inhibit_Hex(short module, int pattern) { //return values //0: pattern of inhibit written successfully //1: module out of range or not present if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; } v812_modules[module-1].registers->pattern_inhibit = pattern; return 0; } //****************************************************************************** int V812_Set_Output_Width(short module, short channel_block, short width) { //channel_block: 0 for ch0-ch7, 1 for ch8-ch15 //return values //0: width set successful //1: module out of range or not present //2: channel_block out of range //3: width out of range (width between 0 (15 ns) and 255 (250 ns), non-linear relation) if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; } if(!((channel_block>=0) && (channel_block<=1))) { return 2; } if(!((width>=0) && (width<=255))) { return 3; } v812_modules[module-1].registers->output_width[channel_block] = width; return 0; } //****************************************************************************** int V812_Set_Dead_Time(short module, short channel_block, short dead_time) { //channel_block: 0 for ch0-ch7, 1 for ch8-ch15 //return values //0: dead time set successful //1: module out of range or not present //2: channel_block out of range //3: dead time out of range (dead time between 0 (150 ns) and 255 (2 us)) if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; } if(!((channel_block>=0) && (channel_block<=1))) { return 2; } if(!((dead_time>=0) && (dead_time<=255))) { return 3; } v812_modules[module-1].registers->dead_time[channel_block] = dead_time; return 0; } //****************************************************************************** int V812_Set_Majority_Level(short module, short majority_level) { //majority_level according to Technical Information Manual, p. 17 //return values //0: majority level set succesful //1: module out of range or not present //2: majority level out of range (1 to 20) u_short majority_threshold; if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; } if(!((majority_level>=1) && (majority_level<=20))) { return 2; } majority_threshold = (double) (majority_level*50-25)/4 + 0.5; //Why + 0.5? This is necessary for the correct calculation of the nearest integer since double-variables are truncated when converted to integer v812_modules[module-1].registers->majority_threshold = majority_threshold; return 0; } int V812_Set_Majority_Threshold(short module, short majority_threshold) { //majority_threshold according to Technical Information Manual, p. 17 //return values //0: majority threshold set succesful //1: module out of range or not present //2: majority threshold out of range (1 to 255) if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; } if(!((majority_threshold>=1) && (majority_threshold<=255))) { return 2; } v812_modules[module-1].registers->majority_threshold = majority_threshold; return 0; } //****************************************************************************** int V812_Test_Pulse(short module) { //return values //0: test pulse generated successfully //1: module out of range or not present if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; } v812_modules[module-1].registers->test_pulse = 0xFFFF; return 0; } //****************************************************************************** int V812_Print_Info(void) { //return values //0: print to stdio successful u_short manufacturer, type, version, sn, i; for(i=0; imanufacturer_type; manufacturer &= 0xFC00; // 0b1111 1100 0000 0000 type = v812_modules[i].registers->manufacturer_type; type &= 0x03FF; // 0b0000 0011 1111 1111 version = v812_modules[i].registers->version_serialnumber; version &= 0xF000; // 0b1111 0000 0000 0000 sn = v812_modules[i].registers->version_serialnumber; sn &= 0x0FFF; // 0b0000 1111 1111 1111 printf("Manufacturer: 0x%04x\nType: 0x%04x\nVersion: 0x%04x\nSerial Number:0x%04x\n\n", manufacturer, type, version, sn); } return 0; } //****************************************************************************** VME_ErrorCode_t V812_Close(void) { VME_ErrorCode_t error_code; u_short i; for(i=0; i