1 |
|
---|
2 |
|
---|
3 | //******************************************************************************
|
---|
4 | //Constants
|
---|
5 | //******************************************************************************
|
---|
6 |
|
---|
7 | #define NMAX_V812_MODULES 10 //maximum 65535, probably more than enough...
|
---|
8 | #define V812_CHANNELS 16
|
---|
9 | #include "v812.h"
|
---|
10 | //******************************************************************************
|
---|
11 | //Type definitions
|
---|
12 | //******************************************************************************
|
---|
13 |
|
---|
14 |
|
---|
15 | //******************************************************************************
|
---|
16 | //Global Variables
|
---|
17 | //******************************************************************************
|
---|
18 |
|
---|
19 | v812_module_t v812_modules[NMAX_V812_MODULES];
|
---|
20 |
|
---|
21 | //******************************************************************************
|
---|
22 | //Function Definitions
|
---|
23 | //******************************************************************************
|
---|
24 |
|
---|
25 | VME_ErrorCode_t V812_Open(void)
|
---|
26 | {
|
---|
27 | u_int tmp_virtual_address, tmp_base_address;
|
---|
28 | u_short i=0;
|
---|
29 | VME_ErrorCode_t error_code;
|
---|
30 | VME_MasterMap_t master_map;
|
---|
31 |
|
---|
32 | master_map.vmebus_address = 0x00010000;
|
---|
33 | master_map.window_size = 0x1000;
|
---|
34 | master_map.address_modifier = VME_A24;
|
---|
35 | master_map.options = 0;
|
---|
36 |
|
---|
37 | for(i=0; i<NMAX_V812_MODULES; i++) {
|
---|
38 | v812_modules[i].present = 0;
|
---|
39 | }
|
---|
40 |
|
---|
41 | //opening the file containing the base addresses
|
---|
42 | FILE *datfile = fopen("v812_base.dat","r");
|
---|
43 | char line[256];
|
---|
44 |
|
---|
45 | i=0;
|
---|
46 | if (datfile!=NULL) {
|
---|
47 | while(fgets(line,255,datfile)) {
|
---|
48 |
|
---|
49 | //excluding comment lines
|
---|
50 | if(line[0] == '%') {
|
---|
51 | continue;
|
---|
52 | }
|
---|
53 |
|
---|
54 | //reading the hex address
|
---|
55 | if(!sscanf(&line[2],"%8x",&tmp_base_address)) {
|
---|
56 | printf("Reading input file v812_base.dat: non-comment line without address found. Please delete or comment this line.\n");
|
---|
57 | }
|
---|
58 |
|
---|
59 | //check address, assign to the master map
|
---|
60 | if(tmp_base_address & 0x0000FFFF) {
|
---|
61 | printf("Reading input file v812_base.dat: 0x%08x is no valid base address (0xXXXX0000)\n",tmp_base_address);
|
---|
62 | continue;
|
---|
63 | }
|
---|
64 | if(i>=NMAX_V812_MODULES) {
|
---|
65 | 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");
|
---|
66 | break;
|
---|
67 | }
|
---|
68 | master_map.vmebus_address = tmp_base_address;
|
---|
69 |
|
---|
70 | if(error_code = VME_MasterMap(&master_map,&v812_modules[i].master_mapping)) {
|
---|
71 | VME_ErrorPrint(error_code);
|
---|
72 | return error_code;
|
---|
73 | }
|
---|
74 |
|
---|
75 | if(error_code = VME_MasterMapVirtualAddress(v812_modules[i].master_mapping,&tmp_virtual_address)) {
|
---|
76 | VME_ErrorPrint(error_code);
|
---|
77 | return error_code;
|
---|
78 | }
|
---|
79 |
|
---|
80 | v812_modules[i].registers = (v812_registers_t *) tmp_virtual_address;
|
---|
81 |
|
---|
82 | if(v812_modules[i].registers->manufacturer_type==0x0851) {
|
---|
83 | //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);
|
---|
84 | v812_modules[i].present = 1;
|
---|
85 | }
|
---|
86 | else {
|
---|
87 | 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);
|
---|
88 | v812_modules[i].present = 0;
|
---|
89 | if(error_code = VME_MasterUnmap(v812_modules[i].master_mapping)) {
|
---|
90 | VME_ErrorPrint(error_code);
|
---|
91 | return error_code;
|
---|
92 | }
|
---|
93 | }
|
---|
94 |
|
---|
95 | i++;
|
---|
96 | }
|
---|
97 | fclose(datfile);
|
---|
98 | }
|
---|
99 | else { printf("File v812_base.dat containing the base addresses of the v812-modules not found.\n"); error_code = VME_FILE; return error_code; }
|
---|
100 |
|
---|
101 | return VME_SUCCESS;
|
---|
102 | }
|
---|
103 |
|
---|
104 | //******************************************************************************
|
---|
105 |
|
---|
106 | int V812_Set_Threshold(short module, short channel, short threshold)
|
---|
107 | {
|
---|
108 | //return values
|
---|
109 | //0: threshold set successful
|
---|
110 | //1: module out of range or not present
|
---|
111 | //2: channel number out of range
|
---|
112 | //3: threshold out of range (threshold in mV between -1 mV and -255 mV)
|
---|
113 |
|
---|
114 | if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; }
|
---|
115 | if(!((channel>=0) && (channel<=15))) { return 2; }
|
---|
116 | if(!((threshold>=1) && (channel<=255))) { return 3; }
|
---|
117 | v812_modules[module-1].registers->threshold_ch[channel] = threshold;
|
---|
118 | return 0;
|
---|
119 |
|
---|
120 | /* comment on little/big endian: the Intel architecture uses little Endian coding,
|
---|
121 | whereas the VME-Standard uses big Endian (to my knowledge). Nonetheless the thresholds
|
---|
122 | can be written directly to the module memory since the thresholds are saved as 8 bit
|
---|
123 | words located at the adress of the short integer (according to the Technical Information
|
---|
124 | Manual MOD. V 812 Series, p 16). */
|
---|
125 | }
|
---|
126 |
|
---|
127 | //******************************************************************************
|
---|
128 |
|
---|
129 | int V812_Set_Pattern_Inhibit(short module, char channels[16])
|
---|
130 | {
|
---|
131 | //return values
|
---|
132 | //0: pattern of inhibit written successfully
|
---|
133 | //1: module out of range or not present
|
---|
134 | if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; }
|
---|
135 |
|
---|
136 | //create the pattern of inhibit
|
---|
137 | u_short pattern = 0;
|
---|
138 | int i;
|
---|
139 | for(i=0; i<16; i++) {
|
---|
140 | if(channels[i]!=0) {
|
---|
141 | switch(i) {
|
---|
142 | case 0: pattern |= 0x0001; break;
|
---|
143 | case 1: pattern |= 0x0002; break;
|
---|
144 | case 2: pattern |= 0x0004; break;
|
---|
145 | case 3: pattern |= 0x0008; break;
|
---|
146 | case 4: pattern |= 0x0010; break;
|
---|
147 | case 5: pattern |= 0x0020; break;
|
---|
148 | case 6: pattern |= 0x0040; break;
|
---|
149 | case 7: pattern |= 0x0080; break;
|
---|
150 | case 8: pattern |= 0x0100; break;
|
---|
151 | case 9: pattern |= 0x0200; break;
|
---|
152 | case 10: pattern |= 0x0400; break;
|
---|
153 | case 11: pattern |= 0x0800; break;
|
---|
154 | case 12: pattern |= 0x1000; break;
|
---|
155 | case 13: pattern |= 0x2000; break;
|
---|
156 | case 14: pattern |= 0x4000; break;
|
---|
157 | case 15: pattern |= 0x8000; break;
|
---|
158 | }
|
---|
159 | }
|
---|
160 | }
|
---|
161 | v812_modules[module-1].registers->pattern_inhibit = pattern;
|
---|
162 | return 0;
|
---|
163 | }
|
---|
164 | int V812_Set_Pattern_Inhibit_Hex(short module, int pattern)
|
---|
165 | {
|
---|
166 | //return values
|
---|
167 | //0: pattern of inhibit written successfully
|
---|
168 | //1: module out of range or not present
|
---|
169 | if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; }
|
---|
170 |
|
---|
171 | v812_modules[module-1].registers->pattern_inhibit = pattern;
|
---|
172 | return 0;
|
---|
173 | }
|
---|
174 | //******************************************************************************
|
---|
175 |
|
---|
176 | int V812_Set_Output_Width(short module, short channel_block, short width)
|
---|
177 | {
|
---|
178 | //channel_block: 0 for ch0-ch7, 1 for ch8-ch15
|
---|
179 |
|
---|
180 | //return values
|
---|
181 | //0: width set successful
|
---|
182 | //1: module out of range or not present
|
---|
183 | //2: channel_block out of range
|
---|
184 | //3: width out of range (width between 0 (15 ns) and 255 (250 ns), non-linear relation)
|
---|
185 |
|
---|
186 | if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; }
|
---|
187 | if(!((channel_block>=0) && (channel_block<=1))) { return 2; }
|
---|
188 | if(!((width>=0) && (width<=255))) { return 3; }
|
---|
189 | v812_modules[module-1].registers->output_width[channel_block] = width;
|
---|
190 | return 0;
|
---|
191 | }
|
---|
192 |
|
---|
193 | //******************************************************************************
|
---|
194 |
|
---|
195 | int V812_Set_Dead_Time(short module, short channel_block, short dead_time)
|
---|
196 | {
|
---|
197 | //channel_block: 0 for ch0-ch7, 1 for ch8-ch15
|
---|
198 |
|
---|
199 | //return values
|
---|
200 | //0: dead time set successful
|
---|
201 | //1: module out of range or not present
|
---|
202 | //2: channel_block out of range
|
---|
203 | //3: dead time out of range (dead time between 0 (150 ns) and 255 (2 us))
|
---|
204 |
|
---|
205 | if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; }
|
---|
206 | if(!((channel_block>=0) && (channel_block<=1))) { return 2; }
|
---|
207 | if(!((dead_time>=0) && (dead_time<=255))) { return 3; }
|
---|
208 | v812_modules[module-1].registers->dead_time[channel_block] = dead_time;
|
---|
209 | return 0;
|
---|
210 | }
|
---|
211 |
|
---|
212 | //******************************************************************************
|
---|
213 |
|
---|
214 | int V812_Set_Majority_Level(short module, short majority_level)
|
---|
215 | {
|
---|
216 | //majority_level according to Technical Information Manual, p. 17
|
---|
217 |
|
---|
218 | //return values
|
---|
219 | //0: majority level set succesful
|
---|
220 | //1: module out of range or not present
|
---|
221 | //2: majority level out of range (1 to 20)
|
---|
222 |
|
---|
223 | u_short majority_threshold;
|
---|
224 |
|
---|
225 | if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; }
|
---|
226 | if(!((majority_level>=1) && (majority_level<=20))) { return 2; }
|
---|
227 |
|
---|
228 | majority_threshold = (double) (majority_level*50-25)/4 + 0.5;
|
---|
229 | //Why + 0.5? This is necessary for the correct calculation of the nearest integer since double-variables are truncated when converted to integer
|
---|
230 |
|
---|
231 | v812_modules[module-1].registers->majority_threshold = majority_threshold;
|
---|
232 | return 0;
|
---|
233 | }
|
---|
234 | int V812_Set_Majority_Threshold(short module, short majority_threshold)
|
---|
235 | {
|
---|
236 | //majority_threshold according to Technical Information Manual, p. 17
|
---|
237 |
|
---|
238 | //return values
|
---|
239 | //0: majority threshold set succesful
|
---|
240 | //1: module out of range or not present
|
---|
241 | //2: majority threshold out of range (1 to 255)
|
---|
242 |
|
---|
243 | if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; }
|
---|
244 | if(!((majority_threshold>=1) && (majority_threshold<=255))) { return 2; }
|
---|
245 | v812_modules[module-1].registers->majority_threshold = majority_threshold;
|
---|
246 | return 0;
|
---|
247 | }
|
---|
248 |
|
---|
249 | //******************************************************************************
|
---|
250 |
|
---|
251 | int V812_Test_Pulse(short module)
|
---|
252 | {
|
---|
253 | //return values
|
---|
254 | //0: test pulse generated successfully
|
---|
255 | //1: module out of range or not present
|
---|
256 |
|
---|
257 | if((module>NMAX_V812_MODULES) || (v812_modules[module-1].present != 1)) { return 1; }
|
---|
258 | v812_modules[module-1].registers->test_pulse = 0xFFFF;
|
---|
259 | return 0;
|
---|
260 | }
|
---|
261 |
|
---|
262 | //******************************************************************************
|
---|
263 |
|
---|
264 | int V812_Print_Info(void)
|
---|
265 | {
|
---|
266 | //return values
|
---|
267 | //0: print to stdio successful
|
---|
268 |
|
---|
269 | u_short manufacturer, type, version, sn, i;
|
---|
270 |
|
---|
271 | for(i=0; i<NMAX_V812_MODULES; i++) {
|
---|
272 | if(v812_modules[i].present != 1) {
|
---|
273 | printf("Module %i is not present.\n",i+1);
|
---|
274 | continue;
|
---|
275 | }
|
---|
276 |
|
---|
277 | printf("v812-module %i (master mapping %i) found:\n",i+1,v812_modules[i].master_mapping);
|
---|
278 | manufacturer = v812_modules[i].registers->manufacturer_type; manufacturer &= 0xFC00; // 0b1111 1100 0000 0000
|
---|
279 | type = v812_modules[i].registers->manufacturer_type; type &= 0x03FF; // 0b0000 0011 1111 1111
|
---|
280 | version = v812_modules[i].registers->version_serialnumber; version &= 0xF000; // 0b1111 0000 0000 0000
|
---|
281 | sn = v812_modules[i].registers->version_serialnumber; sn &= 0x0FFF; // 0b0000 1111 1111 1111
|
---|
282 | printf("Manufacturer: 0x%04x\nType: 0x%04x\nVersion: 0x%04x\nSerial Number:0x%04x\n\n", manufacturer, type, version, sn);
|
---|
283 | }
|
---|
284 | return 0;
|
---|
285 | }
|
---|
286 |
|
---|
287 | //******************************************************************************
|
---|
288 |
|
---|
289 |
|
---|
290 | VME_ErrorCode_t V812_Close(void)
|
---|
291 | {
|
---|
292 | VME_ErrorCode_t error_code;
|
---|
293 | u_short i;
|
---|
294 |
|
---|
295 | for(i=0; i<NMAX_V812_MODULES; i++) {
|
---|
296 | if(v812_modules[i].present != 1) continue;
|
---|
297 |
|
---|
298 | printf("Closing v812-module %i with master mapping %i...",i+1,v812_modules[i].master_mapping);
|
---|
299 | if(error_code = VME_MasterUnmap(v812_modules[i].master_mapping)) {
|
---|
300 | VME_ErrorPrint(error_code);
|
---|
301 | return error_code;
|
---|
302 | }
|
---|
303 | printf("closed.\n");
|
---|
304 | }
|
---|
305 |
|
---|
306 | return VME_SUCCESS;
|
---|
307 | }
|
---|
308 |
|
---|
309 | //******************************************************************************
|
---|