00001 /********************************************************************\ 00002 00003 Name: frontend.c 00004 Created by: Stefan Ritt 00005 00006 Contents: Experiment specific readout code (user part) of 00007 Midas frontend. This example simulates a "trigger 00008 event" and a "scaler event" which are filled with 00009 CAMAC or random data. The trigger event is filled 00010 with two banks (ADC0 and TDC0), the scaler event 00011 with one bank (SCLR). 00012 00013 $Log: frontend.c,v $ 00014 Revision 1.22 2004/01/08 08:40:08 midas 00015 Implemented standard indentation 00016 00017 Revision 1.21 2003/05/12 15:20:11 midas 00018 Removed test code 00019 00020 Revision 1.20 2003/05/09 07:40:04 midas 00021 Added extra parameter to cm_get_environment 00022 00023 Revision 1.19 2003/04/28 15:33:05 midas 00024 Fixed compiler warnings 00025 00026 Revision 1.18 2003/04/25 14:49:46 midas 00027 Removed HBOOK code 00028 00029 Revision 1.17 2003/04/23 15:08:43 midas 00030 Decreased N_TDC to 4 00031 00032 Revision 1.16 2003/04/14 13:31:17 midas 00033 Enabled trigger_bank_list 00034 00035 Revision 1.15 2003/04/14 13:17:01 midas 00036 Added bank description 00037 00038 Revision 1.14 2002/05/16 21:09:53 midas 00039 Added max_event_size_frag 00040 00041 Revision 1.11 2000/08/21 10:32:51 midas 00042 Added max_event_size, set event_buffer_size = 10*max_event_size 00043 00044 Revision 1.10 2000/03/13 18:53:29 pierre 00045 - Added 2nd arg in readout functions (offset for Super event) 00046 00047 Revision 1.9 2000/03/02 22:00:00 midas 00048 Added number of subevents as zero 00049 00050 Revision 1.8 1999/02/24 16:27:01 midas 00051 Added some "real" readout code 00052 00053 Revision 1.7 1999/01/20 09:03:38 midas 00054 Added LAM_SOURCE_CRATE and LAM_SOURCE_STATION macros 00055 00056 Revision 1.6 1999/01/19 10:27:30 midas 00057 Use new LAM_SOURCE and LAM_STATION macros 00058 00059 Revision 1.5 1998/11/09 09:14:41 midas 00060 Added code to simulate random data 00061 00062 Revision 1.4 1998/10/29 14:27:46 midas 00063 Added note about FE_ERR_HW in frontend_init() 00064 00065 Revision 1.3 1998/10/28 15:50:58 midas 00066 Changed lam to DWORD 00067 00068 Revision 1.2 1998/10/12 12:18:58 midas 00069 Added Log tag in header 00070 00071 00072 \********************************************************************/ 00073 00074 #include <stdio.h> 00075 #include <stdlib.h> 00076 #include "midas.h" 00077 #include "mcstd.h" 00078 #include "experim.h" 00079 00080 /* make frontend functions callable from the C framework */ 00081 #ifdef __cplusplus 00082 extern "C" { 00083 #endif 00084 00085 /*-- Globals -------------------------------------------------------*/ 00086 00087 /* The frontend name (client name) as seen by other MIDAS clients */ 00088 char *frontend_name = "Sample Frontend"; 00089 /* The frontend file name, don't change it */ 00090 char *frontend_file_name = __FILE__; 00091 00092 /* frontend_loop is called periodically if this variable is TRUE */ 00093 BOOL frontend_call_loop = FALSE; 00094 00095 /* a frontend status page is displayed with this frequency in ms */ 00096 INT display_period = 3000; 00097 00098 /* maximum event size produced by this frontend */ 00099 INT max_event_size = 10000; 00100 00101 /* maximum event size for fragmented events (EQ_FRAGMENTED) */ 00102 INT max_event_size_frag = 5 * 1024 * 1024; 00103 00104 /* buffer size to hold events */ 00105 INT event_buffer_size = 10 * 10000; 00106 00107 /* number of channels */ 00108 #define N_ADC 4 00109 #define N_TDC 4 00110 #define N_SCLR 4 00111 00112 /* CAMAC crate and slots */ 00113 #define CRATE 0 00114 #define SLOT_IO 23 00115 #define SLOT_ADC 1 00116 #define SLOT_TDC 2 00117 #define SLOT_SCLR 3 00118 00119 /*-- Function declarations -----------------------------------------*/ 00120 00121 INT frontend_init(); 00122 INT frontend_exit(); 00123 INT begin_of_run(INT run_number, char *error); 00124 INT end_of_run(INT run_number, char *error); 00125 INT pause_run(INT run_number, char *error); 00126 INT resume_run(INT run_number, char *error); 00127 INT frontend_loop(); 00128 00129 INT read_trigger_event(char *pevent, INT off); 00130 INT read_scaler_event(char *pevent, INT off); 00131 00132 /*-- Bank definitions ----------------------------------------------*/ 00133 00134 ADC0_BANK_STR(adc0_bank_str); 00135 00136 BANK_LIST trigger_bank_list[] = { 00137 {"ADC0", TID_STRUCT, sizeof(ADC0_BANK), adc0_bank_str} 00138 , 00139 {"TDC0", TID_WORD, N_TDC, NULL} 00140 , 00141 00142 {""} 00143 , 00144 }; 00145 00146 BANK_LIST scaler_bank_list[] = { 00147 {"SCLR", TID_DWORD, N_ADC, NULL} 00148 , 00149 {""} 00150 , 00151 }; 00152 00153 /*-- Equipment list ------------------------------------------------*/ 00154 00155 #undef USE_INT 00156 00157 EQUIPMENT equipment[] = { 00158 00159 {"Trigger", /* equipment name */ 00160 {1, 0, /* event ID, trigger mask */ 00161 "SYSTEM", /* event buffer */ 00162 #ifdef USE_INT 00163 EQ_INTERRUPT, /* equipment type */ 00164 #else 00165 EQ_POLLED, /* equipment type */ 00166 #endif 00167 LAM_SOURCE(0, 0xFFFFFF), /* event source crate 0, all stations */ 00168 "MIDAS", /* format */ 00169 TRUE, /* enabled */ 00170 RO_RUNNING | /* read only when running */ 00171 RO_ODB, /* and update ODB */ 00172 500, /* poll for 500ms */ 00173 0, /* stop run after this event limit */ 00174 0, /* number of sub events */ 00175 0, /* don't log history */ 00176 "", "", "",} 00177 , 00178 read_trigger_event, /* readout routine */ 00179 NULL, NULL, 00180 trigger_bank_list, /* bank list */ 00181 } 00182 , 00183 00184 {"Scaler", /* equipment name */ 00185 {2, 0, /* event ID, trigger mask */ 00186 "SYSTEM", /* event buffer */ 00187 EQ_PERIODIC | EQ_MANUAL_TRIG, /* equipment type */ 00188 0, /* event source */ 00189 "MIDAS", /* format */ 00190 TRUE, /* enabled */ 00191 RO_RUNNING | RO_TRANSITIONS | /* read when running and on transitions */ 00192 RO_ODB, /* and update ODB */ 00193 10000, /* read every 10 sec */ 00194 0, /* stop run after this event limit */ 00195 0, /* number of sub events */ 00196 0, /* log history */ 00197 "", "", "",} 00198 , 00199 read_scaler_event, /* readout routine */ 00200 NULL, NULL, 00201 scaler_bank_list, /* bank list */ 00202 } 00203 , 00204 00205 {""} 00206 }; 00207 00208 #ifdef __cplusplus 00209 } 00210 #endif 00211 /********************************************************************\ 00212 Callback routines for system transitions 00213 00214 These routines are called whenever a system transition like start/ 00215 stop of a run occurs. The routines are called on the following 00216 occations: 00217 00218 frontend_init: When the frontend program is started. This routine 00219 should initialize the hardware. 00220 00221 frontend_exit: When the frontend program is shut down. Can be used 00222 to releas any locked resources like memory, commu- 00223 nications ports etc. 00224 00225 begin_of_run: When a new run is started. Clear scalers, open 00226 rungates, etc. 00227 00228 end_of_run: Called on a request to stop a run. Can send 00229 end-of-run event and close run gates. 00230 00231 pause_run: When a run is paused. Should disable trigger events. 00232 00233 resume_run: When a run is resumed. Should enable trigger events. 00234 00235 \********************************************************************//*-- Frontend Init -------------------------------------------------*/ 00236 INT frontend_init() 00237 { 00238 /* hardware initialization */ 00239 00240 cam_init(); 00241 cam_crate_clear(CRATE); 00242 cam_crate_zinit(CRATE); 00243 00244 /* enable LAM in IO unit */ 00245 camc(CRATE, SLOT_IO, 0, 26); 00246 00247 /* enable LAM in crate controller */ 00248 cam_lam_enable(CRATE, SLOT_IO); 00249 00250 /* reset external LAM Flip-Flop */ 00251 camo(CRATE, SLOT_IO, 1, 16, 0xFF); 00252 camo(CRATE, SLOT_IO, 1, 16, 0); 00253 00254 /* print message and return FE_ERR_HW if frontend should not be started */ 00255 00256 return SUCCESS; 00257 } 00258 00259 /*-- Frontend Exit -------------------------------------------------*/ 00260 00261 INT frontend_exit() 00262 { 00263 return SUCCESS; 00264 } 00265 00266 /*-- Begin of Run --------------------------------------------------*/ 00267 00268 INT begin_of_run(INT run_number, char *error) 00269 { 00270 /* put here clear scalers etc. */ 00271 00272 return SUCCESS; 00273 } 00274 00275 /*-- End of Run ----------------------------------------------------*/ 00276 00277 INT end_of_run(INT run_number, char *error) 00278 { 00279 return SUCCESS; 00280 } 00281 00282 /*-- Pause Run -----------------------------------------------------*/ 00283 00284 INT pause_run(INT run_number, char *error) 00285 { 00286 return SUCCESS; 00287 } 00288 00289 /*-- Resuem Run ----------------------------------------------------*/ 00290 00291 INT resume_run(INT run_number, char *error) 00292 { 00293 return SUCCESS; 00294 } 00295 00296 /*-- Frontend Loop -------------------------------------------------*/ 00297 00298 INT frontend_loop() 00299 { 00300 /* if frontend_call_loop is true, this routine gets called when 00301 the frontend is idle or once between every event */ 00302 return SUCCESS; 00303 } 00304 00305 /*------------------------------------------------------------------*/ 00306 00307 /********************************************************************\ 00308 00309 Readout routines for different events 00310 00311 \********************************************************************/ 00312 00313 /*-- Trigger event routines ----------------------------------------*/ 00314 00315 INT poll_event(INT source, INT count, BOOL test) 00316 /* Polling routine for events. Returns TRUE if event 00317 is available. If test equals TRUE, don't return. The test 00318 flag is used to time the polling */ 00319 { 00320 int i; 00321 DWORD lam; 00322 00323 for (i = 0; i < count; i++) { 00324 cam_lam_read(LAM_SOURCE_CRATE(source), &lam); 00325 00326 if (lam & LAM_SOURCE_STATION(source)) 00327 if (!test) 00328 return lam; 00329 } 00330 00331 return 0; 00332 } 00333 00334 /*-- Interrupt configuration ---------------------------------------*/ 00335 00336 INT interrupt_configure(INT cmd, INT source, PTYPE adr) 00337 { 00338 switch (cmd) { 00339 case CMD_INTERRUPT_ENABLE: 00340 break; 00341 case CMD_INTERRUPT_DISABLE: 00342 break; 00343 case CMD_INTERRUPT_ATTACH: 00344 break; 00345 case CMD_INTERRUPT_DETACH: 00346 break; 00347 } 00348 return SUCCESS; 00349 } 00350 00351 /*-- Event readout -------------------------------------------------*/ 00352 00353 INT read_trigger_event(char *pevent, INT off) 00354 { 00355 ADC0_BANK *adc0_bank; 00356 WORD *pdata, a; 00357 INT q, timeout; 00358 00359 /* init bank structure */ 00360 bk_init(pevent); 00361 00362 /* create structured ADC0 bank */ 00363 bk_create(pevent, "ADC0", TID_STRUCT, &adc0_bank); 00364 00365 /* ADC0 variables can be accessed directly via adc0_bank->adc0 or 00366 as an array using pdata */ 00367 pdata = (WORD *) adc0_bank; 00368 00369 /* wait for ADC conversion */ 00370 for (timeout = 100; timeout > 0; timeout--) { 00371 camc_q(CRATE, SLOT_ADC, 0, 8, &q); 00372 if (q) 00373 break; 00374 } 00375 if (timeout == 0) 00376 ss_printf(0, 10, "No ADC gate!"); 00377 00378 /* use following code to read out real CAMAC ADC */ 00379 /* 00380 for (a=0 ; a<N_ADC ; a++) 00381 cami(CRATE, SLOT_ADC, a, 0, pdata++); 00382 */ 00383 00384 /* Use following code to "simulate" data */ 00385 for (a = 0; a < N_ADC; a++) 00386 *pdata++ = rand() % 1024; 00387 00388 /* clear ADC */ 00389 camc(CRATE, SLOT_ADC, 0, 9); 00390 00391 bk_close(pevent, pdata); 00392 00393 /* create variable length TDC bank */ 00394 bk_create(pevent, "TDC0", TID_WORD, &pdata); 00395 00396 /* use following code to read out real CAMAC TDC */ 00397 /* 00398 for (a=0 ; a<N_TDC ; a++) 00399 cami(CRATE, SLOT_TDC, a, 0, pdata++); 00400 */ 00401 00402 /* Use following code to "simulate" data */ 00403 for (a = 0; a < N_TDC; a++) 00404 *pdata++ = rand() % 1024; 00405 00406 /* clear TDC */ 00407 camc(CRATE, SLOT_TDC, 0, 9); 00408 00409 bk_close(pevent, pdata); 00410 00411 /* clear IO unit LAM */ 00412 camc(CRATE, SLOT_IO, 0, 10); 00413 00414 /* clear LAM in crate controller */ 00415 cam_lam_clear(CRATE, SLOT_IO); 00416 00417 /* reset external LAM Flip-Flop */ 00418 camo(CRATE, SLOT_IO, 1, 16, 0xFF); 00419 camo(CRATE, SLOT_IO, 1, 16, 0); 00420 00421 ss_sleep(10); 00422 00423 return bk_size(pevent); 00424 } 00425 00426 /*-- Scaler event --------------------------------------------------*/ 00427 00428 INT read_scaler_event(char *pevent, INT off) 00429 { 00430 DWORD *pdata, a; 00431 00432 /* init bank structure */ 00433 bk_init(pevent); 00434 00435 /* create SCLR bank */ 00436 bk_create(pevent, "SCLR", TID_DWORD, &pdata); 00437 00438 /* read scaler bank */ 00439 for (a = 0; a < N_SCLR; a++) 00440 cam24i(CRATE, SLOT_SCLR, a, 0, pdata++); 00441 00442 bk_close(pevent, pdata); 00443 00444 return bk_size(pevent); 00445 }