source: fact/tools/hvMCUtest/hvMCUtest.cc@ 16318

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