| 1 |
|
|---|
| 2 | /********************************************************************\
|
|---|
| 3 |
|
|---|
| 4 | Name: HV.cc
|
|---|
| 5 |
|
|---|
| 6 | Created by: Sebastian Commichau, November 2008
|
|---|
| 7 | commichau@phys.ethz.ch
|
|---|
| 8 |
|
|---|
| 9 | Contents: Main class for HV supply
|
|---|
| 10 |
|
|---|
| 11 | Requirements: Both libftdi and libusb are required for the
|
|---|
| 12 | communication - see manual for more details.
|
|---|
| 13 |
|
|---|
| 14 | libftdi: library for talking with FTDI USB <-> Serial
|
|---|
| 15 | converter, UM245R.
|
|---|
| 16 | http://www.intra2net.com/de/produkte/opensource/ftdi/
|
|---|
| 17 |
|
|---|
| 18 | libusb: library for talking to USB devices from
|
|---|
| 19 | user-space. Also needed by libftdi.
|
|---|
| 20 | http://libusb.wiki.sourceforge.net/
|
|---|
| 21 |
|
|---|
| 22 | \********************************************************************/
|
|---|
| 23 |
|
|---|
| 24 |
|
|---|
| 25 | #include "HV.h"
|
|---|
| 26 |
|
|---|
| 27 |
|
|---|
| 28 | HV::HV(char** usbdevice, int* usbdevicenumber, FILE* f): fNumberOfBoards(0) {
|
|---|
| 29 |
|
|---|
| 30 | int i = 0, j = 0, ret = 0;
|
|---|
| 31 |
|
|---|
| 32 | char manufacturer[STR_LENGTH], type[STR_LENGTH], serial[STR_LENGTH];
|
|---|
| 33 |
|
|---|
| 34 | bzero(manufacturer, sizeof(manufacturer));
|
|---|
| 35 | bzero(type, sizeof(type));
|
|---|
| 36 | bzero(serial, sizeof(serial));
|
|---|
| 37 |
|
|---|
| 38 | fprintf(stdout,"Scan: ");
|
|---|
| 39 |
|
|---|
| 40 | // Search for FTDI devices
|
|---|
| 41 | for (i = 0;i<MAX_NUM_HVBOARDS;i++)
|
|---|
| 42 | ftdi_init(&ftdic[i]);
|
|---|
| 43 |
|
|---|
| 44 | ftdi_init(&ftdic_dummy);
|
|---|
| 45 |
|
|---|
| 46 | if ((i = ftdi_usb_find_all(&ftdic_dummy, &devlist, USB_VENDOR, USB_PRODUCT)) < 0)
|
|---|
| 47 | fprintf(stderr,"error: ftdi_usb_find_all failed: %d (%s)\n", i, ftdi_get_error_string(&ftdic_dummy));
|
|---|
| 48 |
|
|---|
| 49 | fprintf(stdout,"found %d FTDI device(s)\n", i);
|
|---|
| 50 | i = 0;
|
|---|
| 51 |
|
|---|
| 52 | // Obtain information on FTDI devices
|
|---|
| 53 | for (curdev = devlist; (curdev != NULL && i<MAX_NUM_HVBOARDS); i++) {
|
|---|
| 54 |
|
|---|
| 55 | fprintf(stdout,"Device %d:\n", i);
|
|---|
| 56 |
|
|---|
| 57 | if ((ret = ftdi_usb_get_strings(&ftdic_dummy, curdev->dev, manufacturer, STR_LENGTH, type, STR_LENGTH, serial, STR_LENGTH)) < 0) {
|
|---|
| 58 | fprintf(stderr," Error: ftdi_usb_get_strings failed: %d (%s)\n", ret, ftdi_get_error_string(&ftdic_dummy));
|
|---|
| 59 | break;
|
|---|
| 60 | }
|
|---|
| 61 |
|
|---|
| 62 | fprintf(stdout," Manufacturer: %s - Type: %s - Serial: %s\n", manufacturer, type, serial);
|
|---|
| 63 |
|
|---|
| 64 | // Fixme: the following code should be revised!
|
|---|
| 65 | while (j<MAX_NUM_HVBOARDS) {
|
|---|
| 66 | if (strcmp(serial,usbdevice[j])==0)
|
|---|
| 67 | break;
|
|---|
| 68 | j++;
|
|---|
| 69 | }
|
|---|
| 70 |
|
|---|
| 71 | if (j<MAX_NUM_HVBOARDS) {
|
|---|
| 72 | ret = ftdi_usb_open_desc(&ftdic[fNumberOfBoards], USB_VENDOR, USB_PRODUCT, type, serial);
|
|---|
| 73 |
|
|---|
| 74 | // Fixme: this function does not work properly if there is more than one device???!!!
|
|---|
| 75 | // ret = ftdi_usb_open(&ftdic[fNumberOfBoards], USB_VENDOR, USB_PRODUCT);
|
|---|
| 76 |
|
|---|
| 77 | if (ret < 0 && ret != -5)
|
|---|
| 78 | fprintf(stderr," Error: unable to open FTDI device: %d (%s)\n", i, ftdi_get_error_string(&ftdic[fNumberOfBoards]));
|
|---|
| 79 | else {
|
|---|
| 80 |
|
|---|
| 81 | ftdi_set_baudrate(&ftdic[fNumberOfBoards], USB_BAUDRATE);
|
|---|
| 82 | ftdi_usb_reset(&ftdic[fNumberOfBoards]);
|
|---|
| 83 | ftdi_usb_purge_buffers(&ftdic[fNumberOfBoards]);
|
|---|
| 84 | /*
|
|---|
| 85 | The FTDI chip keeps data in the internal buffer for a specific
|
|---|
| 86 | amount of time if the buffer is not full yet to decrease load on the usb bus.
|
|---|
| 87 | */
|
|---|
| 88 | ftdi_set_latency_timer(&ftdic[fNumberOfBoards], USB_LATENCY_TIMER);
|
|---|
| 89 |
|
|---|
| 90 | fHVBoard[fNumberOfBoards] = new HVBoard(serial, usbdevicenumber[j], &ftdic[fNumberOfBoards]);
|
|---|
| 91 | fNumberOfBoards++;
|
|---|
| 92 | /*
|
|---|
| 93 | fprintf(stdout," FTDI open succeeded\n");
|
|---|
| 94 | fprintf(stdout," Baudrate: %d\n", ftdic[i].baudrate);
|
|---|
| 95 | fprintf(stdout," USB_read_timeout: %d\n", ftdic[i].usb_read_timeout);
|
|---|
| 96 | fprintf(stdout," USB_write_timeout: %d\n", ftdic[i].usb_write_timeout);
|
|---|
| 97 | */
|
|---|
| 98 | }
|
|---|
| 99 |
|
|---|
| 100 | }
|
|---|
| 101 | else
|
|---|
| 102 | fprintf(stdout," Warning: found new USB device - check configuration file!\n");
|
|---|
| 103 |
|
|---|
| 104 | j=0;
|
|---|
| 105 |
|
|---|
| 106 | curdev = curdev->next;
|
|---|
| 107 | }
|
|---|
| 108 |
|
|---|
| 109 | // Re-order board numbering otherwise it is determined by the connection sequence
|
|---|
| 110 | ArrangeHVBoards(fHVBoard,fNumberOfBoards);
|
|---|
| 111 |
|
|---|
| 112 | }
|
|---|
| 113 |
|
|---|
| 114 |
|
|---|
| 115 | /* Bubble-sort HV boards according to board number */
|
|---|
| 116 | void HV::ArrangeHVBoards(HVBoard** fHVBoard, int size) {
|
|---|
| 117 |
|
|---|
| 118 | HVBoard* tmp;
|
|---|
| 119 |
|
|---|
| 120 | for (int i=size-1;i>0;--i)
|
|---|
| 121 | for (int pos=0;pos<i;++pos)
|
|---|
| 122 | if (fHVBoard[pos]->GetBoardNumber()>fHVBoard[pos+1]->GetBoardNumber()) {
|
|---|
| 123 | tmp = fHVBoard[pos];
|
|---|
| 124 | fHVBoard[pos] = fHVBoard[pos+1];
|
|---|
| 125 | fHVBoard[pos+1] = tmp;
|
|---|
| 126 | }
|
|---|
| 127 |
|
|---|
| 128 | }
|
|---|
| 129 |
|
|---|
| 130 |
|
|---|
| 131 | HV::~HV() {
|
|---|
| 132 |
|
|---|
| 133 | int i, ret = 0;
|
|---|
| 134 |
|
|---|
| 135 | for (i=0;i<fNumberOfBoards;i++) {
|
|---|
| 136 | fprintf(stdout,"Device %d: ",i);
|
|---|
| 137 |
|
|---|
| 138 | ret = ftdi_usb_close(&ftdic[i]);
|
|---|
| 139 |
|
|---|
| 140 | if (ret < 0)
|
|---|
| 141 | fprintf(stderr, "Unable to close FTDI device: %d (%s)\n", i, ftdi_get_error_string(&ftdic[i]));
|
|---|
| 142 | else
|
|---|
| 143 | fprintf(stdout, "FTDI close succeeded\n");
|
|---|
| 144 |
|
|---|
| 145 | delete fHVBoard[i];
|
|---|
| 146 | }
|
|---|
| 147 |
|
|---|
| 148 | fprintf(stdout,"FTDI list free\n");
|
|---|
| 149 | ftdi_list_free(&devlist);
|
|---|
| 150 |
|
|---|
| 151 | for (i=0;i<MAX_NUM_HVBOARDS;i++)
|
|---|
| 152 | ftdi_deinit(&ftdic[i]);
|
|---|
| 153 |
|
|---|
| 154 | ftdi_deinit(&ftdic_dummy);
|
|---|
| 155 |
|
|---|
| 156 | }
|
|---|
| 157 |
|
|---|
| 158 |
|
|---|
| 159 | HVBoard::HVBoard(char* serial, int number, struct ftdi_context* ftdic) : fTimeOut(.5)
|
|---|
| 160 | {
|
|---|
| 161 |
|
|---|
| 162 | FTDI_C = ftdic;
|
|---|
| 163 | sprintf(Serial,"%s",serial);
|
|---|
| 164 | BoardNumber = number;
|
|---|
| 165 |
|
|---|
| 166 | }
|
|---|
| 167 |
|
|---|
| 168 |
|
|---|
| 169 | HVBoard::~HVBoard() {
|
|---|
| 170 |
|
|---|
| 171 | }
|
|---|
| 172 |
|
|---|
| 173 |
|
|---|
| 174 | /* For test purposes only - never use this function with a real HV board!!! */
|
|---|
| 175 | void HVBoard::TestIO() {
|
|---|
| 176 |
|
|---|
| 177 | int ret = 0, werrors = 0, rerrors = 0, mismatches = 0;
|
|---|
| 178 |
|
|---|
| 179 | unsigned char wbuf[BUFFER_LENGTH], rbuf[BUFFER_LENGTH];
|
|---|
| 180 |
|
|---|
| 181 | for (int i=0;i<=0XFF;i++) {
|
|---|
| 182 |
|
|---|
| 183 | wbuf[0] = (unsigned char)i;
|
|---|
| 184 |
|
|---|
| 185 | #ifdef DO_CAST
|
|---|
| 186 | ret = ftdi_write_data(FTDI_C,(char*)wbuf,1);
|
|---|
| 187 | #endif
|
|---|
| 188 | ret = ftdi_write_data(FTDI_C,wbuf,1);
|
|---|
| 189 |
|
|---|
| 190 | if (ret < 0)
|
|---|
| 191 | werrors++;
|
|---|
| 192 |
|
|---|
| 193 | #ifdef DO_CAST
|
|---|
| 194 | ret = ftdi_read_data(FTDI_C,(char*)rbuf,1);
|
|---|
| 195 | #endif
|
|---|
| 196 | ret = ftdi_write_data(FTDI_C,wbuf,1);
|
|---|
| 197 |
|
|---|
| 198 | if (ret < 0)
|
|---|
| 199 | rerrors++;
|
|---|
| 200 |
|
|---|
| 201 | if (rbuf[0]!=wbuf[0]) {
|
|---|
| 202 | mismatches++;
|
|---|
| 203 | fprintf(stdout,"Mismatch - written: 0X%.2X read: 0X%.2X\n",wbuf[0],rbuf[0]);
|
|---|
| 204 | }
|
|---|
| 205 | }
|
|---|
| 206 | fprintf(stdout, "Result: %d write errors, %d read errors, %d mismatches\n",werrors,rerrors,mismatches);
|
|---|
| 207 | }
|
|---|
| 208 |
|
|---|
| 209 |
|
|---|
| 210 | int HVBoard::Write(unsigned char* data, int size) {
|
|---|
| 211 | #ifdef DO_CAST
|
|---|
| 212 | return ftdi_write_data(FTDI_C, (char*)data, size);
|
|---|
| 213 | #endif
|
|---|
| 214 | return ftdi_write_data(FTDI_C, data, size);
|
|---|
| 215 | }
|
|---|
| 216 |
|
|---|
| 217 |
|
|---|
| 218 | int HVBoard::Read(unsigned char* data, int size) {
|
|---|
| 219 | #ifdef DO_CAST
|
|---|
| 220 | return ftdi_read_data(FTDI_C, (char*)data, size);
|
|---|
| 221 | #endif
|
|---|
| 222 | return ftdi_read_data(FTDI_C, data, size);
|
|---|
| 223 | }
|
|---|
| 224 |
|
|---|
| 225 |
|
|---|
| 226 | /*
|
|---|
| 227 | TRead: read from HV Board until fTimeOut has been reached
|
|---|
| 228 |
|
|---|
| 229 | Returns:
|
|---|
| 230 | 0 if a read error has occured
|
|---|
| 231 | 1 on success
|
|---|
| 232 | -1 if fTimeOut [s] has been exceeded
|
|---|
| 233 | */
|
|---|
| 234 | int HVBoard::TRead(FILE* fptr, unsigned char* rbuf, bool verbose) {
|
|---|
| 235 |
|
|---|
| 236 | char str[STR_LENGTH];
|
|---|
| 237 |
|
|---|
| 238 | long int t1, t2;
|
|---|
| 239 | int ret = 0;
|
|---|
| 240 |
|
|---|
| 241 | t1 = GetMicroSeconds();
|
|---|
| 242 |
|
|---|
| 243 | do {
|
|---|
| 244 |
|
|---|
| 245 | if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) {
|
|---|
| 246 | if (verbose)
|
|---|
| 247 | if (ret < 0) {
|
|---|
| 248 | fprintf(stderr, " Read error: %d (%s)\n", ret, ftdi_get_error_string(FTDI_C));
|
|---|
| 249 | return 0;
|
|---|
| 250 | }
|
|---|
| 251 | }
|
|---|
| 252 | else {
|
|---|
| 253 |
|
|---|
| 254 | if (verbose)
|
|---|
| 255 | fprintf(fptr," %d byte(s) read:\n",ret);
|
|---|
| 256 |
|
|---|
| 257 | for (int i=0;i<ret;i++) {
|
|---|
| 258 | sPrintByteBin(rbuf[i],str);
|
|---|
| 259 | if (verbose)
|
|---|
| 260 | fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,rbuf[i]);
|
|---|
| 261 | }
|
|---|
| 262 | return 1;
|
|---|
| 263 | }
|
|---|
| 264 |
|
|---|
| 265 | t2 = GetMicroSeconds();
|
|---|
| 266 |
|
|---|
| 267 | if ((t2-t1)/1000000. >= fTimeOut) {
|
|---|
| 268 | fprintf(fptr," Warning: timeout exceeded\n");
|
|---|
| 269 | return -1;
|
|---|
| 270 | }
|
|---|
| 271 |
|
|---|
| 272 | } while(1);
|
|---|
| 273 |
|
|---|
| 274 | }
|
|---|
| 275 |
|
|---|
| 276 |
|
|---|
| 277 | /* Reset HV board - uses TRead() and has same return values */
|
|---|
| 278 | int HVBoard::Reset(FILE* fptr, unsigned char* rbuf, bool verbose) {
|
|---|
| 279 |
|
|---|
| 280 | char str[STR_LENGTH];
|
|---|
| 281 |
|
|---|
| 282 | unsigned char wbuf[] = {REG_RESET,0,0};
|
|---|
| 283 |
|
|---|
| 284 | if (Write(wbuf,3) < 1) {
|
|---|
| 285 | fprintf(fptr," Error: could not write to HV board\n");
|
|---|
| 286 | return 0;
|
|---|
| 287 | }
|
|---|
| 288 |
|
|---|
| 289 | if (verbose)
|
|---|
| 290 | fprintf(fptr," 3 bytes written:\n");
|
|---|
| 291 |
|
|---|
| 292 | for (int i=0;i<3;i++) {
|
|---|
| 293 | sPrintByteBin(wbuf[i],str);
|
|---|
| 294 | if (verbose)
|
|---|
| 295 | fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,wbuf[i]);
|
|---|
| 296 | }
|
|---|
| 297 |
|
|---|
| 298 | return TRead(fptr,rbuf,verbose);
|
|---|
| 299 |
|
|---|
| 300 | }
|
|---|
| 301 |
|
|---|
| 302 |
|
|---|
| 303 | /* Read status register - uses TRead() and has same return values */
|
|---|
| 304 | int HVBoard::GetStatus(FILE* fptr, unsigned char* rbuf, bool verbose) {
|
|---|
| 305 |
|
|---|
| 306 | char str[STR_LENGTH];
|
|---|
| 307 |
|
|---|
| 308 | unsigned char wbuf[] = {REG_STATUS,0,0};
|
|---|
| 309 |
|
|---|
| 310 | if (Write(wbuf,3) < 1) {
|
|---|
| 311 | if (verbose)
|
|---|
| 312 | fprintf(fptr," Error: could not write to HV board\n");
|
|---|
| 313 | return 0;
|
|---|
| 314 | }
|
|---|
| 315 |
|
|---|
| 316 | if (verbose)
|
|---|
| 317 | fprintf(fptr," 3 bytes written:\n");
|
|---|
| 318 |
|
|---|
| 319 | for (int i=0;i<3;i++) {
|
|---|
| 320 | sPrintByteBin(wbuf[i],str);
|
|---|
| 321 | if (verbose)
|
|---|
| 322 | fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,wbuf[i]);
|
|---|
| 323 | }
|
|---|
| 324 |
|
|---|
| 325 | return TRead(fptr,rbuf,verbose);
|
|---|
| 326 |
|
|---|
| 327 | }
|
|---|
| 328 |
|
|---|
| 329 |
|
|---|
| 330 | /* Set high voltage - uses TRead() and has same return values */
|
|---|
| 331 | int HVBoard::SetHV(FILE* fptr, int chain, unsigned int channel, unsigned int hv, unsigned char* rbuf, bool verbose) {
|
|---|
| 332 |
|
|---|
| 333 | char str[STR_LENGTH];
|
|---|
| 334 |
|
|---|
| 335 | unsigned char wbuf[] = {0,0,0};
|
|---|
| 336 |
|
|---|
| 337 | if (!(hv>=0.0 && hv<=0X3FFF)) {
|
|---|
| 338 | fprintf(fptr," Error: HV beyond limits [0 - 0x3FFF]\n");
|
|---|
| 339 | return 0;
|
|---|
| 340 | }
|
|---|
| 341 |
|
|---|
| 342 |
|
|---|
| 343 | switch (chain) {
|
|---|
| 344 |
|
|---|
| 345 | case 0: wbuf[0] = REG_HV0; break;
|
|---|
| 346 | case 1: wbuf[0] = REG_HV1; break;
|
|---|
| 347 | case 2: wbuf[0] = REG_HV2; break;
|
|---|
| 348 | case 3: wbuf[0] = REG_HV3; break;
|
|---|
| 349 |
|
|---|
| 350 | default : fprintf(fptr," Error: chain %d does not exist\n",chain); return 0;
|
|---|
| 351 |
|
|---|
| 352 | }
|
|---|
| 353 |
|
|---|
| 354 | // Assemble bytes
|
|---|
| 355 | wbuf[0] |= (unsigned char)((channel >> 2) & 0X00000007); // Add address [A4-A3]
|
|---|
| 356 | wbuf[1] |= (unsigned char)((hv >> 8) & 0X000000FF); // Add [D13-D8]
|
|---|
| 357 | wbuf[1] |= (unsigned char)((channel << 6) & 0X000000C0); // Add [A1-A0]
|
|---|
| 358 | wbuf[2] |= (unsigned char)(hv & 0X000000FF); // Add [D7-D0]
|
|---|
| 359 |
|
|---|
| 360 |
|
|---|
| 361 | if (Write(wbuf,3) < 1) {
|
|---|
| 362 | fprintf(fptr," Error: could not write to HV board\n");
|
|---|
| 363 | return 0;
|
|---|
| 364 | }
|
|---|
| 365 |
|
|---|
| 366 | if (verbose)
|
|---|
| 367 | fprintf(fptr," 3 bytes written:\n");
|
|---|
| 368 |
|
|---|
| 369 | for (int i=0;i<3;i++) {
|
|---|
| 370 | sPrintByteBin(wbuf[i],str);
|
|---|
| 371 | if (verbose)
|
|---|
| 372 | fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,wbuf[i]);
|
|---|
| 373 | }
|
|---|
| 374 |
|
|---|
| 375 | return TRead(fptr,rbuf,verbose);
|
|---|
| 376 |
|
|---|
| 377 | }
|
|---|
| 378 |
|
|---|
| 379 |
|
|---|
| 380 | /* Set reference voltage - uses TRead() and has same return values */
|
|---|
| 381 | int HVBoard::SetVRef(FILE* fptr, int chain, unsigned int vref, unsigned char* rbuf, bool verbose) {
|
|---|
| 382 |
|
|---|
| 383 | char str[STR_LENGTH];
|
|---|
| 384 |
|
|---|
| 385 | unsigned char wbuf[] = {0,0,0};
|
|---|
| 386 |
|
|---|
| 387 | if (!(vref>=0 && vref<=0X3FFF)) {
|
|---|
| 388 | if (verbose)
|
|---|
| 389 | fprintf(fptr," Error: vref beyond limits\n");
|
|---|
| 390 | return 0;
|
|---|
| 391 | }
|
|---|
| 392 |
|
|---|
| 393 | switch (chain) {
|
|---|
| 394 |
|
|---|
| 395 | case 0: wbuf[0] = REG_VREF0; break;
|
|---|
| 396 | case 1: wbuf[0] = REG_VREF1; break;
|
|---|
| 397 | case 2: wbuf[0] = REG_VREF2; break;
|
|---|
| 398 | case 3: wbuf[0] = REG_VREF3; break;
|
|---|
| 399 |
|
|---|
| 400 | default : fprintf(fptr," Error: chain %d does not exist\n",chain); return 0;
|
|---|
| 401 |
|
|---|
| 402 | }
|
|---|
| 403 |
|
|---|
| 404 | // Assemble bytes
|
|---|
| 405 | wbuf[0] |= (unsigned char)((vref >> 13) & 0X0000000F); // Add [D13]
|
|---|
| 406 | wbuf[1] |= (unsigned char)((vref >> 5) & 0X000000FF); // Add [D12-D5]
|
|---|
| 407 | wbuf[2] |= (unsigned char)((vref << 3) & 0X000000FF); // Add [D4-D0]
|
|---|
| 408 |
|
|---|
| 409 | // PD bits (device clear) are not used
|
|---|
| 410 | wbuf[0] &= ~REG_PD1;
|
|---|
| 411 | wbuf[0] &= ~REG_PD2;
|
|---|
| 412 |
|
|---|
| 413 | if (Write(wbuf,3) < 1) {
|
|---|
| 414 | fprintf(fptr," Error: could not write to HV board\n");
|
|---|
| 415 | return 0;
|
|---|
| 416 | }
|
|---|
| 417 |
|
|---|
| 418 | if (verbose)
|
|---|
| 419 | fprintf(fptr," 3 bytes written:\n");
|
|---|
| 420 |
|
|---|
| 421 | for (int i=0;i<3;i++) {
|
|---|
| 422 | sPrintByteBin(wbuf[i],str);
|
|---|
| 423 | if (verbose)
|
|---|
| 424 | fprintf(fptr," Byte %d: %s| 0X%.2X\n",i,str,wbuf[i]);
|
|---|
| 425 | }
|
|---|
| 426 |
|
|---|
| 427 | return TRead(fptr,rbuf,verbose);
|
|---|
| 428 |
|
|---|
| 429 | }
|
|---|
| 430 |
|
|---|
| 431 |
|
|---|
| 432 | /*
|
|---|
| 433 | Init: initialize (synchronize) HV board - to be used before any other access!
|
|---|
| 434 |
|
|---|
| 435 | Returns 0 if an error has occured, 1 on success.
|
|---|
| 436 |
|
|---|
| 437 | Before any other access the HV board communication has to be synchronized.
|
|---|
| 438 | Each write access requires three bytes to be sent from the computer to the
|
|---|
| 439 | HV board. The HV board sends back one byte containing status information.
|
|---|
| 440 |
|
|---|
| 441 | The normal initialization procedure would be the following:
|
|---|
| 442 |
|
|---|
| 443 | 1. send one byte (0X80 = REG_STATUS).
|
|---|
| 444 | 1.1. try reading as long as fTimeOut is not exceeded.
|
|---|
| 445 |
|
|---|
| 446 | 2. send again one byte (0X00).
|
|---|
| 447 | 2.1. try reading as long as fTimeOut is not exceeded.
|
|---|
| 448 |
|
|---|
| 449 | 3. send again one byte (0X00).
|
|---|
| 450 | 3.1. try reading again as long as fTimeOut is not exceeded.
|
|---|
| 451 |
|
|---|
| 452 | Note: from time to time there are problems when performing only 3 trials! Reason:
|
|---|
| 453 | the first byte written by libftdi can get lost somewhere between
|
|---|
| 454 | libusb <-> kernel <-> FTDI chip. I haven't found yet any solution to this.
|
|---|
| 455 | To solve the issue, another byte is sent to assure a proper synchronization,
|
|---|
| 456 | even though the first byte was lost:
|
|---|
| 457 |
|
|---|
| 458 | 4. send again one byte (0X00).
|
|---|
| 459 | 4.1. try reading again as long as fTimeOut is not exceeded; if fTimeOut
|
|---|
| 460 | has been exceeded return.
|
|---|
| 461 |
|
|---|
| 462 | See also: http://lists.omnipotent.net/pipermail/lcdproc/2008-June/012235.html
|
|---|
| 463 | */
|
|---|
| 464 | int HVBoard::Init(bool verbose) {
|
|---|
| 465 |
|
|---|
| 466 | unsigned char wbuf = REG_STATUS;
|
|---|
| 467 | unsigned char rbuf[STR_LENGTH];
|
|---|
| 468 |
|
|---|
| 469 | int trial = 1;
|
|---|
| 470 | int ret = 0;
|
|---|
| 471 |
|
|---|
| 472 | long int t1, t2;
|
|---|
| 473 |
|
|---|
| 474 |
|
|---|
| 475 | // First send 0X80
|
|---|
| 476 | if (Write(&wbuf,1) < 1) {
|
|---|
| 477 | if (verbose)
|
|---|
| 478 | fprintf(stdout," Error: could not write to HV board\n");
|
|---|
| 479 | return 0;
|
|---|
| 480 | }
|
|---|
| 481 | else
|
|---|
| 482 | if (verbose)
|
|---|
| 483 | fprintf(stdout," 1 byte written: 0X%.2X\n",wbuf);
|
|---|
| 484 |
|
|---|
| 485 |
|
|---|
| 486 | t1 = GetMicroSeconds();
|
|---|
| 487 |
|
|---|
| 488 |
|
|---|
| 489 | // Read - first trial
|
|---|
| 490 | do {
|
|---|
| 491 |
|
|---|
| 492 | t2 = GetMicroSeconds();
|
|---|
| 493 |
|
|---|
| 494 | if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) {
|
|---|
| 495 | if (verbose)
|
|---|
| 496 | if (ret < 0) {
|
|---|
| 497 | fprintf(stderr, " Read error: %d (%s)\n",ret,ftdi_get_error_string(FTDI_C));
|
|---|
| 498 | return 0;
|
|---|
| 499 | }
|
|---|
| 500 | }
|
|---|
| 501 | else {
|
|---|
| 502 | if (verbose)
|
|---|
| 503 | fprintf(stdout," %d byte(s) read:",ret);
|
|---|
| 504 | for (int i=0;i<ret;i++)
|
|---|
| 505 | if (verbose)
|
|---|
| 506 | fprintf(stdout," 0X%.2X",rbuf[i]);
|
|---|
| 507 | if (verbose)
|
|---|
| 508 | fprintf(stdout,"\n");
|
|---|
| 509 | fprintf(stdout," Success: initialization done (%d trial)\n",trial);
|
|---|
| 510 | return 1;
|
|---|
| 511 | }
|
|---|
| 512 |
|
|---|
| 513 | if ((t2-t1)/1000000. > fTimeOut) {
|
|---|
| 514 | if (verbose)
|
|---|
| 515 | fprintf(stdout," Warning: timeout exceeded\n");
|
|---|
| 516 | trial++;
|
|---|
| 517 |
|
|---|
| 518 | // Second write
|
|---|
| 519 | wbuf = 0;
|
|---|
| 520 | if (Write(&wbuf,1) < 1) {
|
|---|
| 521 | if (verbose)
|
|---|
| 522 | fprintf(stdout," Error: could not write to HV board\n");
|
|---|
| 523 | return 0;
|
|---|
| 524 | }
|
|---|
| 525 | else
|
|---|
| 526 | if (verbose)
|
|---|
| 527 | fprintf(stdout," 1 byte written: 0X%.2X\n",wbuf);
|
|---|
| 528 |
|
|---|
| 529 | t1 = GetMicroSeconds();
|
|---|
| 530 |
|
|---|
| 531 | // Read - second trial
|
|---|
| 532 | do {
|
|---|
| 533 |
|
|---|
| 534 | t2 = GetMicroSeconds();
|
|---|
| 535 |
|
|---|
| 536 | if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) {
|
|---|
| 537 | if (verbose)
|
|---|
| 538 | if (ret < 0) {
|
|---|
| 539 | fprintf(stderr, " Read error: %d (%s)\n",ret,ftdi_get_error_string(FTDI_C));
|
|---|
| 540 | return 0;
|
|---|
| 541 | }
|
|---|
| 542 | }
|
|---|
| 543 | else {
|
|---|
| 544 | if (verbose)
|
|---|
| 545 | fprintf(stdout," %d byte(s) read:",ret);
|
|---|
| 546 | for (int i=0;i<ret;i++)
|
|---|
| 547 | if (verbose)
|
|---|
| 548 | fprintf(stdout," 0X%.2X",rbuf[i]);
|
|---|
| 549 | if (verbose)
|
|---|
| 550 | fprintf(stdout,"\n");
|
|---|
| 551 | fprintf(stdout," Success: initialization done (%d trials)\n",trial);
|
|---|
| 552 | return 1;
|
|---|
| 553 | }
|
|---|
| 554 |
|
|---|
| 555 | if ((t2-t1)/1000000. > fTimeOut) {
|
|---|
| 556 | if (verbose)
|
|---|
| 557 | fprintf(stdout," Warning: timeout exceeded\n");
|
|---|
| 558 | trial++;
|
|---|
| 559 |
|
|---|
| 560 | // Third write
|
|---|
| 561 | wbuf = 0;
|
|---|
| 562 | if (Write(&wbuf,1) < 1) {
|
|---|
| 563 | if (verbose)
|
|---|
| 564 | fprintf(stdout," Error: could not write to HV board\n");
|
|---|
| 565 | return 0;
|
|---|
| 566 | }
|
|---|
| 567 | else
|
|---|
| 568 | if (verbose)
|
|---|
| 569 | fprintf(stdout," 1 byte written: 0X%.2X\n",wbuf);
|
|---|
| 570 |
|
|---|
| 571 |
|
|---|
| 572 | // Read - third trial
|
|---|
| 573 | do {
|
|---|
| 574 |
|
|---|
| 575 | t2 = GetMicroSeconds();
|
|---|
| 576 |
|
|---|
| 577 | if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) {
|
|---|
| 578 | if (verbose)
|
|---|
| 579 | if (ret < 0) {
|
|---|
| 580 | fprintf(stderr, " Read error: %d (%s)\n",ret,ftdi_get_error_string(FTDI_C));
|
|---|
| 581 | return 0;
|
|---|
| 582 | }
|
|---|
| 583 | }
|
|---|
| 584 | else {
|
|---|
| 585 | if (verbose)
|
|---|
| 586 | fprintf(stdout," %d byte(s) read:",ret);
|
|---|
| 587 | for (int i=0;i<ret;i++)
|
|---|
| 588 | if (verbose)
|
|---|
| 589 | fprintf(stdout," 0X%.2X",rbuf[i]);
|
|---|
| 590 | if (verbose)
|
|---|
| 591 | fprintf(stdout,"\n");
|
|---|
| 592 | fprintf(stdout," Success: initialization done (%d trials)\n",trial);
|
|---|
| 593 | return 1;
|
|---|
| 594 | }
|
|---|
| 595 |
|
|---|
| 596 |
|
|---|
| 597 | if ((t2-t1)/1000000. > fTimeOut) {
|
|---|
| 598 | if (verbose)
|
|---|
| 599 | fprintf(stdout," Warning: timeout exceeded\n");
|
|---|
| 600 | trial++;
|
|---|
| 601 |
|
|---|
| 602 | // Fourth write
|
|---|
| 603 | wbuf = 0;
|
|---|
| 604 | if (Write(&wbuf,1) < 1) {
|
|---|
| 605 | if (verbose)
|
|---|
| 606 | fprintf(stdout," Error: could not write to HV board\n");
|
|---|
| 607 | return 0;
|
|---|
| 608 | }
|
|---|
| 609 | else
|
|---|
| 610 | if (verbose)
|
|---|
| 611 | fprintf(stdout," 1 byte written: 0X%.2X\n",wbuf);
|
|---|
| 612 |
|
|---|
| 613 |
|
|---|
| 614 | // Read - fourth and last trial
|
|---|
| 615 | do {
|
|---|
| 616 |
|
|---|
| 617 | t2 = GetMicroSeconds();
|
|---|
| 618 |
|
|---|
| 619 | if ((ret = Read(rbuf,BUFFER_LENGTH)) < 1) {
|
|---|
| 620 | if (verbose)
|
|---|
| 621 | if (ret < 0) {
|
|---|
| 622 | fprintf(stderr, " Read error: %d (%s)\n",ret,ftdi_get_error_string(FTDI_C));
|
|---|
| 623 | return 0;
|
|---|
| 624 | }
|
|---|
| 625 | }
|
|---|
| 626 | else {
|
|---|
| 627 | if (verbose)
|
|---|
| 628 | fprintf(stdout," %d byte(s) read:",ret);
|
|---|
| 629 | for (int i=0;i<ret;i++)
|
|---|
| 630 | if (verbose)
|
|---|
| 631 | fprintf(stdout," 0X%.2X",rbuf[i]);
|
|---|
| 632 | if (verbose)
|
|---|
| 633 | fprintf(stdout,"\n");
|
|---|
| 634 | fprintf(stdout," Success: initialization done (%d trials)\n",trial);
|
|---|
| 635 | return 1;
|
|---|
| 636 | }
|
|---|
| 637 |
|
|---|
| 638 | if ((t2-t1)/1000000. > fTimeOut) {
|
|---|
| 639 | if (verbose)
|
|---|
| 640 | fprintf(stdout," Error: timeout exceeded - initialization failed (%d trials)\n",trial);
|
|---|
| 641 | return 0;
|
|---|
| 642 |
|
|---|
| 643 | }
|
|---|
| 644 |
|
|---|
| 645 | } while (1);
|
|---|
| 646 |
|
|---|
| 647 | }
|
|---|
| 648 |
|
|---|
| 649 | } while (1);
|
|---|
| 650 |
|
|---|
| 651 | }
|
|---|
| 652 |
|
|---|
| 653 | } while (1);
|
|---|
| 654 |
|
|---|
| 655 | }
|
|---|
| 656 |
|
|---|
| 657 | } while (1);
|
|---|
| 658 |
|
|---|
| 659 |
|
|---|
| 660 | return 0;
|
|---|
| 661 | }
|
|---|
| 662 |
|
|---|
| 663 |
|
|---|
| 664 | /* Decode wrap counter */
|
|---|
| 665 | int HVBoard::DecodeWrap(unsigned char* rbuf) {
|
|---|
| 666 |
|
|---|
| 667 | return (*rbuf & 0X07);
|
|---|
| 668 |
|
|---|
| 669 | }
|
|---|
| 670 |
|
|---|
| 671 |
|
|---|
| 672 | /* Decode over current bits */
|
|---|
| 673 | void HVBoard::DecodeOC(bool OC[], unsigned char* rbuf) {
|
|---|
| 674 |
|
|---|
| 675 | for (int i=0;i<MAX_NUM_CHAINS;i++)
|
|---|
| 676 | OC[i]=(*rbuf & (0X08 << i));
|
|---|
| 677 | }
|
|---|
| 678 |
|
|---|
| 679 |
|
|---|
| 680 | /* Decode bit indicating manual reset */
|
|---|
| 681 | bool HVBoard::DecodeReset(unsigned char* rbuf) {
|
|---|
| 682 |
|
|---|
| 683 | return (bool)(*rbuf & 0X80);
|
|---|
| 684 |
|
|---|
| 685 | }
|
|---|
| 686 |
|
|---|
| 687 |
|
|---|