source: fact/tools/vchvtest/vchvtest.cc@ 12948

Last change on this file since 12948 was 202, checked in by ogrimm, 15 years ago
Improved test command
  • Property svn:executable set to *
File size: 12.4 KB
Line 
1/**************************************************************\
2
3 Test program for new bias supply
4
5 Oliver Grimm
6
7\**************************************************************/
8
9#include <stdio.h>
10#include <termios.h>
11#include <unistd.h>
12
13#include <ctype.h>
14#include <sys/time.h>
15
16#include <readline/readline.h>
17#include <readline/history.h>
18
19#include "HV.h"
20
21#define MAX_NUM_TOKEN 10
22
23
24// Global variables
25HVBoard **fHVBoard;
26const char *Param[MAX_NUM_TOKEN]; // For parser
27int NParam;
28int NumCrates;
29int FirstCrate;
30int LastCrate;
31bool Repeat = false;
32bool Verbose;
33
34// Function prototypes
35void cmd_crate(); void cmd_status();
36void cmd_timeout(); void cmd_synch();
37void cmd_send(); void cmd_rst();
38void cmd_rd(); void cmd_gs();
39void cmd_cs(); void cmd_exit();
40void cmd_help(); void cmd_repeat();
41void cmd_config(); void cmd_rate();
42void cmd_test();
43
44int ParseInput(char*, const char *Param[]);
45bool Match(const char *, const char *);
46bool ConvertToDouble(const char *, double *);
47bool ConvertToInt(const char *, int *);
48
49// Branch table for command evaluation
50static const struct CL_Struct { const char *Name;
51 void (*CommandPointer)();
52 int MinNumParameter;
53 const char *Parameters;
54 const char *Help;
55 bool Repeatable;
56 } CommandList[] =
57 {{"crate", &cmd_crate, 0, "<i> [j] | <all>" ,"Address crate i, crates i-j, all crates", false},
58 {"status", &cmd_status, 0, "[i]", "Show status information (for board i)", false},
59 {"config", &cmd_config, 0, "", "Show crate configuration", false},
60 {"timeout", &cmd_timeout, 1, "<secs>", "Set timeout to return from read", false},
61 {"synch", &cmd_synch, 0, "", "Synchronize board(s)", false},
62 {"send", &cmd_send, 1, "<byte1> [byte2] ...", "Send bytes and wait for response", true},
63 {"rst", &cmd_rst, 0, "", "System reset", true},
64 {"rd", &cmd_rd, 2, "<Board> <Channel>", "Read status", true},
65 {"gs", &cmd_gs, 1, "<Voltage>", "Global voltage set", true},
66 {"cs", &cmd_cs, 3, "<Board> <Channel> <Voltage>", "Set channel to voltage", true},
67 {"rate", &cmd_rate, 1, "<n>", "Make n 'rd 0 0' cycles and measure time", false},
68 {"repeat", &cmd_repeat, 1, "<on|off>", "Command repetition (ENTER to stop)", false},
69 {"test", &cmd_test, 1, "<Voltage>", "Set all channels consecutively", false},
70 {"exit", &cmd_exit, 0, "", "Exit program", false},
71 {"help", &cmd_help, 0, "", "Print help", false}};
72
73
74// ================ Main program ================
75int main(int argc, char *argv[]) {
76
77 char Prompt[MAX_COM_SIZE], *Command = NULL;
78 struct termios Termios, Termios_orig;
79
80 printf("\n*** vchvtest (built %s, %s; O. Grimm) ***\n\n",__DATE__,__TIME__);
81 if (argc == 1) {
82 printf("Note: Use FTDI serial numbers as arguments to connect\n");
83 }
84
85
86 // Initialize status variables
87 NumCrates = 0;
88 FirstCrate = 0;
89 LastCrate = -1;
90
91 // Open HV devices
92 fHVBoard = new HVBoard* [argc-1];
93 for (int i=1; i<argc; i++) {
94 fHVBoard[NumCrates] = new HVBoard(i-1, argv[i]);
95 if(fHVBoard[NumCrates]->fDescriptor != -1) NumCrates++;
96 else delete fHVBoard[NumCrates];
97 }
98 LastCrate = NumCrates-1;
99
100 // Set terminal to read single chars
101 if (tcgetattr (1, &Termios_orig) == -1) {
102 printf("Error with tcgetattr() (%s)\n", strerror(errno));
103 exit(EXIT_FAILURE);
104 }
105 Termios = Termios_orig;
106 Termios.c_lflag &= ~(ICANON | ECHO);
107
108 // Command loop
109 while (true) {
110 if (Command != NULL) free(Command); // Free command buffer
111
112 // Assemble prompt
113 if (NumCrates == 0) snprintf(Prompt, sizeof(Prompt), "HV> ");
114 else if (FirstCrate == LastCrate) snprintf(Prompt, sizeof(Prompt), "HV|B%d> ",FirstCrate);
115 else snprintf(Prompt,sizeof(Prompt),"HV|B%d-%d> ",FirstCrate,LastCrate);
116
117 // Read command from console
118 Command = readline(Prompt);
119 if (Command==NULL) {
120 printf("Error reading command line input\n");
121 continue;
122 }
123 if(strlen(Command)>0) add_history(Command);
124 else continue;
125
126 // Set terminal to return single chars
127 if (tcsetattr (1, 0, &Termios) == -1) {
128 printf("Error with tcsetattr() (%s)\n", strerror(errno));
129 exit(EXIT_FAILURE);
130 }
131
132 // Defualt is verbose response
133 Verbose = true;
134
135 // Process command
136 for(int i=0; i<MAX_NUM_TOKEN; i++) Param[i] = ""; // All pointers point initially to empty string
137 NParam = ParseInput(Command, Param);
138
139 bool Found=false;
140 int N;
141 for(unsigned int CmdNumber=0; CmdNumber<sizeof(CommandList)/sizeof(CL_Struct); CmdNumber++) {
142 if (Match(Param[0], CommandList[CmdNumber].Name)) {
143 if(NParam-1 < CommandList[CmdNumber].MinNumParameter) {
144 printf("Usage: %s %s\n", CommandList[CmdNumber].Name, CommandList[CmdNumber].Parameters);
145 }
146 else do {
147 (*CommandList[CmdNumber].CommandPointer)();
148 ioctl(STDIN_FILENO, FIONREAD, &N);
149 } while(CommandList[CmdNumber].Repeatable && Repeat && N==0);
150 Found = true;
151 break;
152 }
153 } // for()
154
155 if (!Found) printf("Unknown command '%s'\n",Param[0]);
156
157 // Set terminal back to line buffering
158 if (tcsetattr (1, 0, &Termios_orig) == -1) {
159 printf("Error with tcsetattr() (%s)\n", strerror(errno));
160 exit(EXIT_FAILURE);
161 }
162 } // while()
163}
164
165// Print help
166void cmd_help() {
167
168 char Buffer[MAX_COM_SIZE];
169 for(unsigned int i=0; i<sizeof(CommandList)/sizeof(CL_Struct); i++) {
170 snprintf(Buffer, sizeof(Buffer), "%s %s", CommandList[i].Name, CommandList[i].Parameters);
171 printf("%-32s%s\n", Buffer, CommandList[i].Help);
172 }
173 printf("\nAccepted prefixes for integers: 'b' binary, '0' octal, '0x' hexadecimal\n");
174}
175
176// Select board(s)
177void cmd_crate() {
178
179 int Number;
180
181 if (Match(Param[1],"all")) {
182 FirstCrate = 0;
183 LastCrate = NumCrates-1;
184 return;
185 }
186 if (NParam>=2 && ConvertToInt(Param[1], &Number) && Number>=0 && Number<NumCrates) {
187 FirstCrate = Number;
188 LastCrate = FirstCrate;
189 }
190 if (NParam==3 && ConvertToInt(Param[2], &Number) && Number>=FirstCrate && Number<NumCrates) {
191 LastCrate = Number;
192 }
193}
194
195// System reset
196void cmd_rst() {
197
198 for (int i=FirstCrate; i<=LastCrate; i++) {
199 if (fHVBoard[i]->SystemReset() == 1) {
200 printf("Reset of board %d\n", fHVBoard[i]->BoardNumber);
201 }
202 else printf("Error: Could not reset board %d\n",fHVBoard[i]->BoardNumber);
203 }
204}
205
206// Read channel
207void cmd_rd() {
208
209 int Board=0, Channel=0;
210
211 if (!ConvertToInt(Param[1], &Board) || !ConvertToInt(Param[2], &Channel)) return;
212
213 for (int i=FirstCrate; i<=LastCrate; i++) {
214 if (fHVBoard[i]->ReadChannel(Board, Channel) != 1) {
215 printf("Error: Could not read from board %d\n", fHVBoard[i]->BoardNumber);
216 }
217 }
218}
219
220// Read channel
221void cmd_gs() {
222
223 int Voltage;
224
225 if (!ConvertToInt(Param[1], &Voltage)) return;
226
227 for (int i=FirstCrate; i<=LastCrate; i++) {
228 if (fHVBoard[i]->GlobalSet(Voltage) != 1) {
229 printf("Error: Could not global set board %d\n", fHVBoard[i]->BoardNumber);
230 }
231 }
232}
233
234// Read channel
235void cmd_cs() {
236
237 int Board=0, Channel=0, Voltage=0;
238
239 if (!ConvertToInt(Param[1], &Board) || !ConvertToInt(Param[2], &Channel) || !ConvertToInt(Param[3], &Voltage)) return;
240
241 for (int i=FirstCrate; i<=LastCrate; i++) {
242 if (fHVBoard[i]->ChannelSet(Board, Channel, Voltage) != 1) {
243 printf("Error: Could not channel set board %d\n", fHVBoard[i]->BoardNumber);
244 }
245 }
246}
247
248// Synchronize boards
249void cmd_synch() {
250
251 for (int i=FirstCrate; i<=LastCrate; i++) {
252 if (fHVBoard[i]->SynchBoard()) printf("Synchronized board %d\n", fHVBoard[i]->BoardNumber);
253 else printf("Failed to synchronize board %d\n", fHVBoard[i]->BoardNumber);
254 }
255}
256
257// Switch on all channels consecutively for cabling test
258void cmd_test() {
259
260 Verbose = false;
261
262 // Loop over crates
263 for (int i=FirstCrate; i<=LastCrate; i++) {
264 printf("Testing board %d (q to stop, any other key to continue)\n", fHVBoard[i]->BoardNumber);
265 if (fHVBoard[i]->GlobalSet(0) != 1) {
266 printf("Error: Could not global set board to zero\n");
267 return;
268 }
269
270 for (int k=0; k<MAX_NUM_BOARDS; k++) for (int j=0; j<NUM_CHANNELS; j++) {
271 printf("Board %d, channel %d\n", k, j);
272
273 if (fHVBoard[i]->ChannelSet(k, j, atoi(Param[1])) != 1) {
274 printf(" Error setting voltage\n");
275 return;
276 }
277
278 if (getchar() == 'q') return;
279 }
280 }
281}
282
283// Send bytes and wait for response
284void cmd_send() {
285
286 unsigned char wbuf[MAX_NUM_TOKEN];
287 int Number;
288
289 for (int j=1; j<NParam; j++) {
290 ConvertToInt(Param[j], &Number);
291 wbuf[j-1] = (unsigned char) Number;
292 }
293
294 for (int i=FirstCrate; i<=LastCrate; i++) {
295 fHVBoard[i]->Communicate(wbuf, NParam-1);
296 }
297}
298
299// Measure read speed
300void cmd_rate() {
301
302 struct timeval Start, End;
303 int N = atoi(Param[1]);
304
305 if (N < 1) return;
306 Verbose = false;
307
308 gettimeofday(&Start, NULL);
309 for (int i=0; i<=N; i++) fHVBoard[0]->ReadChannel(0, 0);
310 gettimeofday(&End, NULL);
311
312 double Diff = ((End.tv_sec-Start.tv_sec)*1e6 + End.tv_usec-Start.tv_usec) * 1e-6;
313 printf("%d accesses in %f seconds: rate %.0f Hz, period %.2f ms\n", N, Diff, N/Diff, (Diff*1e3)/N);
314}
315
316// Switch repeat on/off
317void cmd_repeat() {
318
319 if (Match(Param[1],"on")) Repeat = true;
320 else Repeat = false;
321 printf("Auto command repeat is %s\n", Repeat ? "on (Hit return while repeating to stop)" : "off");
322}
323
324// Print status
325void cmd_status() {
326
327 int Board;
328
329 Verbose = false;
330
331 if (NParam==2 && ConvertToInt(Param[1], &Board)) {
332 for (int i=FirstCrate; i<=LastCrate; i++) {
333 for (int j=0; j<NUM_CHANNELS; j++) {
334 if (j%4 == 0) printf("\nChannel %2d ", j);
335 fHVBoard[i]->ReadChannel(Board, j);
336 if (fHVBoard[i]->Status.BoardNumber == -1) printf("Read error ");
337 else printf(" %s %s %5d ", fHVBoard[i]->Status.Overcurrent ? "OC":"--", fHVBoard[i]->Status.Acknowledge ? "OK":"KO",fHVBoard[i]->Status.Current);
338 }
339 printf("\n");
340 }
341 } else {
342 printf(" Auto command repeat is %s\n", Repeat ? "on" : "off");
343 printf(" Total number of HV crates: %d\n", NumCrates);
344 printf(" Active HV crates: %d\n\n", LastCrate - FirstCrate + 1);
345
346 for (int i=FirstCrate; i<=LastCrate; i++) {
347 printf(" Crate %d (%s) Wrap counter: %d Time-out: %.2f s\n",
348 fHVBoard[i]->BoardNumber, fHVBoard[i]->BoardName,
349 fHVBoard[i]->LastWrapCount, fHVBoard[i]->fTimeOut);
350 }
351 }
352}
353
354// Print crate configuration
355void cmd_config() {
356
357 Verbose = false;
358
359 for (int i=FirstCrate; i<=LastCrate; i++) {
360 for (int j=0; j<MAX_NUM_BOARDS; j++) {
361 printf("Board %2d ", j);
362 fHVBoard[i]->ReadChannel(j, 0);
363 if (fHVBoard[i]->Status.BoardNumber == -1) printf("Read error\n");
364 else printf(" %s\n", fHVBoard[i]->Status.Acknowledge ? "OK":"KO");
365 }
366 }
367}
368
369// Set timeout to return from read
370void cmd_timeout() {
371
372 double Timeout;
373
374 if (!ConvertToDouble(Param[1], &Timeout)) return;
375 for (int i=0; i<NumCrates; i++) fHVBoard[i]->fTimeOut = Timeout;
376}
377
378// Exit program (delete HV boards)
379void cmd_exit() {
380
381 for (int i=0; i<NumCrates; i++) delete fHVBoard[i];
382 delete[] fHVBoard;
383
384 exit(EXIT_SUCCESS);
385}
386
387
388// Parse command line for white space and double-quote separated tokens
389int ParseInput(char* Command, const char *Param[]) {
390
391 int Count=0;
392
393 while(Count<MAX_NUM_TOKEN) {
394 while (isspace(*Command)) Command++; // Ignore initial white spaces
395 if(*Command=='\0') break;
396 if (*Command == '\"') {
397 Param[Count] = ++Command;
398 while(*Command!='\"' && *Command!='\0') Command++;
399 }
400 else {
401 Param[Count] = Command;
402 while(!isspace(*Command) && *Command!='\0') Command++;
403 }
404 if(*Command != '\0') *Command++ = '\0';
405 Count++;
406 }
407 return Count;
408}
409
410
411// Check if two strings match (min 1 character must match)
412bool Match(const char *str, const char *cmd) {
413
414 return strncasecmp(str,cmd,strlen(str)==0 ? 1:strlen(str)) ? false:true;
415}
416
417// Convert string to double
418// Returns false if conversion did not stop on whitespace or EOL character
419bool ConvertToDouble(const char *String, double *Result) {
420
421 char *EndPointer;
422
423 *Result = strtod(String, &EndPointer);
424 if(!isspace(*EndPointer) && *EndPointer!='\0') {
425 printf("Error: Wrong number format\n");
426 return false;
427 }
428 return true;
429}
430
431// Convert string to int
432// Returns false if conversion did not stop on whitespace or EOL character
433// Accepted prefixes: 'b' binary, '0' octal, '0x' hexadecimal
434bool ConvertToInt(const char *String, int *Result) {
435
436 char *EndPointer;
437 int Base = 0;
438
439 if (tolower(*String) == 'b') {
440 String++;
441 Base = 2;
442 }
443
444 *Result = (int) strtol(String, &EndPointer, Base);
445 if(!isspace(*EndPointer) && *EndPointer!='\0') {
446 printf("Error: Wrong number format\n");
447 return false;
448 }
449 return true;
450}
Note: See TracBrowser for help on using the repository browser.