00001
00024 #include "di194.h"
00025 #include "di194-internal.h"
00026
00030 bool do_exit;
00031
00032
00033
00050 int di_serial_close(const int COMM_FD)
00051 {
00052 if(COMM_FD > 0)
00053 {
00054 return(close(COMM_FD));
00055 }
00056 else
00057 return(-1);
00058 }
00059
00060
00061
00082 int di_serial_init(const char *COMPORT_FILE)
00083 {
00084 char me[] = "di_serial_init";
00085 struct termios term;
00086 int comm_fd = -1;
00087 const int baud_rate = B4800;
00088
00089
00090 comm_fd = open(COMPORT_FILE, O_RDWR | O_NOCTTY | O_NONBLOCK);
00091
00092
00093 if(comm_fd < 0)
00094 {
00095 fprintf(stderr,
00096 "\n%s: Could not open port %s\n",
00097 me, COMPORT_FILE);
00098 perror("open");
00099 return(comm_fd);
00100 }
00101
00102
00103
00104
00105
00106
00107
00108 if(ioctl(comm_fd, TIOCEXCL) == -1)
00109 {
00110 fprintf(stderr, "Error setting exclusive access to serial port, %s", strerror(errno));
00111 close(comm_fd);
00112 return(-1);
00113 }
00114
00115
00116
00117 if(fcntl(comm_fd, F_SETFL, 0) == -1)
00118 {
00119 fprintf(stderr, "Error setting blocking IO on serial port: %s", strerror(errno));
00120 close(comm_fd);
00121 return(-2);
00122 }
00123
00124
00125 tcgetattr(comm_fd ,&term);
00126
00127
00128 term.c_cflag &= ~CSIZE;
00129 term.c_cflag |= CS8;
00130 term.c_cflag |= HUPCL;
00131 term.c_cflag |= CREAD;
00132 term.c_cflag &= ~CRTSCTS;
00133 term.c_cflag |= IXON;
00134
00135
00136 term.c_oflag &= ~OPOST;
00137
00138
00139 term.c_iflag = IGNBRK|IGNPAR;
00140
00141
00142 term.c_lflag = 0;
00143
00144
00145 term.c_cc[VMIN] = 0;
00146 term.c_cc[VTIME] = (serial_timeout * 10);
00147
00148
00149 cfsetispeed(&term, baud_rate);
00150 cfsetospeed(&term, baud_rate);
00151
00152
00153 tcsetattr(comm_fd, TCSANOW, &term);
00154
00155
00156 usleep(25000);
00157
00158
00159 cfsetispeed(&term, B0);
00160 cfsetospeed(&term, B0);
00161 tcsetattr(comm_fd, TCSANOW, &term);
00162
00163
00164 cfsetospeed(&term, baud_rate);
00165 tcsetattr(comm_fd, TCSANOW, &term);
00166
00167
00168 usleep(25000);
00169
00170
00171 tcflush(comm_fd, TCIOFLUSH);
00172
00173 return(comm_fd);
00174 }
00175
00176
00193 int min(const int A, const int B)
00194 {
00195 return(A < B? A : B);
00196 }
00197
00198
00209 void hex_print_byte(const uint8_t in_byte)
00210 {
00211 printf("%02X ", (int) in_byte);
00212 if(isprint(in_byte))
00213 printf("(%c)", in_byte);
00214 }
00215
00216 int di_stop(const int COMM_FD)
00217 {
00218 return(di_cmd_send(COMM_FD, stop_cmd, sizeof(stop_cmd)));
00219 }
00220
00221
00222 int di_start(const int COMM_FD)
00223 {
00224 return(di_cmd_send(COMM_FD, start_cmd, sizeof(start_cmd)));
00225 }
00226
00227 int di_reset(const int COMM_FD)
00228 {
00229 return(di_cmd_send(COMM_FD, rst_cmd, sizeof(rst_cmd)));
00230 }
00231
00232 int di_serial_num(const int COMM_FD, char *ser_buf)
00233 {
00234 char me[] = "di_serial";
00235 int rc, idx;
00236
00237 rc = di_cmd_send(COMM_FD, sn_cmd, sizeof(sn_cmd));
00238 if(rc != 0)
00239 {
00240 fprintf(stderr,
00241 "\nError sending serial number request, rc=%d\n", rc);
00242 return(1);
00243 }
00244
00245
00246 rc = di_serial_read(COMM_FD, ser_buf, SERIAL_NUM_LEN, serial_timeout);
00247 if(rc != 0)
00248 {
00249
00250 fprintf(stderr, "\n%s: Error reading serial number", me);
00251
00252 if(rc >= 1)
00253 {
00254 fprintf(stderr, "\n%s: Data received was '", me);
00255 for(idx = 0; idx < rc; idx++)
00256 fprintf(stderr, "%02X ",
00257 (int) ser_buf[idx]);
00258 fprintf(stderr, "'\n");
00259 }
00260 return(2);
00261 }
00262
00263 return(0);
00264 }
00265
00266
00267
00288 int di_serial_read(const int COMM_FD, const uint8_t *buf,
00289 const int READ_LEN, const time_t TIMEOUT)
00290 {
00291 char me[] = "di_serial_read";
00292 time_t t_start;
00293 int rc;
00294 int rx_count = 0;
00295
00296 t_start = time(NULL);
00297
00298
00299 while(((time(NULL) - t_start) < TIMEOUT) &&
00300 (rx_count < READ_LEN))
00301 {
00302
00303 rc = read(COMM_FD, (uint8_t *) &buf[rx_count],
00304 (READ_LEN - rx_count));
00305 if(rc < 0)
00306 {
00307
00308 fprintf(stderr, "\n%s: Error on read, rc=%d", me, rc);
00309 return(1);
00310 }
00311 if(rc == 0)
00312 {
00313
00314 usleep(100);
00315 }
00316 else
00317 rx_count += rc;
00318 }
00319
00320
00321 if(rx_count >= READ_LEN)
00322 return(0);
00323 else
00324 {
00325 fprintf(stderr, "\n%s: Short read, got %d of %d expected",
00326 me, rx_count, READ_LEN);
00327 fprintf(stderr, ", elapsed was %u seconds",
00328 (uint32_t) (time(NULL) - t_start));
00329
00330 if(rx_count != 0)
00331 return(rx_count);
00332 else
00333 return(-1);
00334 }
00335 }
00336
00337
00346 void di_cmd_print(const uint8_t *cmd, const int CMD_LEN)
00347 {
00348 char me[] = "di_cmd_print";
00349 int idx;
00350
00351 if(CMD_LEN > 1)
00352 fprintf(stderr, "\n%s: %d-byte command '", me, CMD_LEN);
00353 else if(CMD_LEN == 1)
00354 fprintf(stderr, "\n%s: 1-byte argument '", me);
00355 else
00356 {
00357 fprintf(stderr, "\n%s: Error, invalid cmd length %d",
00358 me, CMD_LEN);
00359 return;
00360 }
00361
00362 for(idx = 0; idx < CMD_LEN; idx++)
00363 {
00364 fprintf(stderr, " %02X", (int) cmd[idx]);
00365
00366 if(isprint(cmd[idx]))
00367 fprintf(stderr, " (%c)", cmd[idx]);
00368 }
00369
00370 fprintf(stderr, "'");
00371 return;
00372 }
00373
00374
00397 bool is_reset_cmd(const uint8_t *cmd, const int CMD_LEN)
00398 {
00399 char me[] = "is_reset_cmd";
00400 int idx;
00401
00402
00403 if((CMD_LEN != 3) || (cmd == NULL))
00404 return(false);
00405
00406 for(idx = 0; idx < CMD_LEN; idx++)
00407 if(cmd[idx] != rst_cmd[idx])
00408 return(false);
00409
00410 return(true);
00411
00412
00413 fprintf(stderr, "\n%s: Reset command found", me);
00414 }
00415
00416
00439 int di_daq_sync(const int COMM_FD)
00440 {
00441 char me[] = "di_daq_sync";
00442 uint8_t sync_buf[5 * sizeof(daq_buf_t)] = "";
00443 int idx, rc, clear_count;
00444 bool found_match = false;
00445
00446
00447
00448 rc = di_serial_read(COMM_FD, sync_buf, (4 * sizeof(daq_buf_t)),
00449 serial_timeout);
00450 if(rc != 0)
00451 {
00452 fprintf(stderr, "\n%s: Error reading\n", me);
00453 return(rc);
00454 }
00455
00456
00457 for(idx = 0; idx < (3 * sizeof(daq_buf_t)); idx++)
00458 {
00459 rc = di_buf_validate(&sync_buf[idx]);
00460 if(rc != 0)
00461 fprintf(stderr, "\n%s: No sync at index %d, rc %d", me, idx, rc);
00462 else
00463 {
00464
00465 found_match = true;
00466 break;
00467 }
00468 }
00469
00470 if(found_match == true)
00471 {
00472
00473 clear_count = idx;
00474
00475 rc = di_serial_read(COMM_FD, sync_buf,
00476 clear_count, serial_timeout);
00477 if(rc != 0)
00478 {
00479 fprintf(stderr, "\n%s: Error on sync read!", me);
00480 return(rc);
00481 }
00482
00483
00484 return(0);
00485 }
00486 else
00487 fprintf(stderr, "\nNo sync\n");
00488
00489
00490 return(-1);
00491 }
00492
00493
00494
00524 int di_cmd_send(const int COMM_FD, const uint8_t *cmd, const int CMD_LEN)
00525 {
00526 char me[] = "di_cmd_send";
00527 int idx, rc;
00528 uint8_t btmp;
00529 int read_len = CMD_LEN;
00530
00531 if(cmd == NULL)
00532 return(-1);
00533
00534
00535
00536
00537 for(idx = 0; idx < CMD_LEN; idx++)
00538 {
00539
00540 rc = write(COMM_FD, &cmd[idx], sizeof(uint8_t));
00541 if(rc != sizeof(uint8_t))
00542 {
00543 fprintf(stderr, "\n%s: Error sending command", me);
00544 return(1);
00545 }
00546
00547
00548 if(cmd[idx] == 0x00)
00549 continue;
00550
00551
00552 rc = di_serial_read(COMM_FD, &btmp,
00553 sizeof(btmp), serial_timeout);
00554 if(rc != 0)
00555 {
00556 fprintf(stderr, "\n%s: Error on command echo read",
00557 me);
00558 return(2);
00559 }
00560
00561 if(btmp != cmd[idx])
00562 {
00563 fprintf(stderr, "\n%s: Cmd was %02X, echo was %02X",
00564 me, (int) cmd[idx], (int) btmp);
00565 }
00566
00567
00568
00569
00570
00571 }
00572
00573
00574 for(idx = 0; idx < (read_len - CMD_LEN); idx++)
00575 {
00576 rc = di_serial_read(COMM_FD, &btmp,
00577 sizeof(btmp), serial_timeout);
00578 if(rc != 0)
00579 {
00580 fprintf(stderr, "\n%s: Error reading trailer bytes\n",
00581 me);
00582 }
00583 }
00584
00585 return(0);
00586 }
00587
00588
00608 int di_initialize(const int COMM_FD, int *num_bits)
00609 {
00610 char me[] = "di_initialize";
00611 int idx, rc;
00612 uint8_t ser_buf[SERIAL_NUM_LEN * 2] = "";
00613 const uint8_t rs194_signature[SERIAL_NUM_LEN + 1] = "0000000000";
00614 const uint8_t rs154_signature[SERIAL_NUM_LEN + 1] = "0000000001";
00615
00616
00617 read(COMM_FD, ser_buf, 1);
00618
00619
00620 di_cmd_send(COMM_FD, odd_cmd, sizeof(odd_cmd));
00621
00622
00623 rc = di_stop(COMM_FD);
00624
00625
00626 rc = di_serial_num(COMM_FD, ser_buf);
00627 if(rc != 0)
00628 return(rc);
00629
00630
00631 if(strncmp(ser_buf, rs194_signature, SERIAL_NUM_LEN) == 0)
00632 {
00633 printf("\nNew (194RS) unit found, skipping enable code download");
00634 *num_bits = 10;
00635 }
00636 else if (strncmp(ser_buf, rs154_signature, SERIAL_NUM_LEN) == 0)
00637 {
00638 printf("\n154RS found, no enable code required");
00639 *num_bits = 12;
00640 }
00641 else
00642 {
00643 printf("\nOld DI-194 found, serial number: '");
00644
00645 for(idx = 0; idx < SERIAL_NUM_LEN; idx++)
00646 printf("%c", ser_buf[idx]);
00647 printf("'\nSending enable key to device");
00648
00649
00650
00651 for(idx = 0; idx < sizeof(di_enable_key); idx++)
00652 {
00653 rc = di_cmd_send(COMM_FD, key_cmd, sizeof(key_cmd));
00654 if(rc != 0)
00655 {
00656 fprintf(stderr, "\n%s: Error sending key command", me);
00657 return(2);
00658 }
00659
00660
00661 rc = di_cmd_send(COMM_FD, &di_enable_key[idx], sizeof(uint8_t));
00662 if(rc != 0)
00663 {
00664 fprintf(stderr, "\n%s: Error sending key byte", me);
00665 return(2);
00666 }
00667 }
00668 }
00669
00670 return(0);
00671 }
00672
00673
00674
00699 int di_configure(const int COMM_FD)
00700 {
00701 char me[] = "di_configure";
00702 int rc;
00703
00704 if(COMM_FD <= 0)
00705 {
00706 fprintf(stderr, "\n%s: Invalid file descriptor %d",
00707 me, COMM_FD);
00708 return(1);
00709 }
00710
00711
00712 rc = di_cmd_send(COMM_FD, all_chan, sizeof(all_chan));
00713 if(rc != 0)
00714 {
00715 fprintf(stderr, "\n%s: Error sending all-channels command",
00716 me);
00717 return(2);
00718 }
00719
00720
00721 rc = di_cmd_send(COMM_FD, dig_chan, sizeof(dig_chan));
00722 if(rc != 0)
00723 {
00724 fprintf(stderr,
00725 "\n%s: Error sending digital channels command", me);
00726 return(2);
00727 }
00728
00729
00730 return(0);
00731 }
00732
00733
00749 char *di_byte_print(const uint8_t in_byte)
00750 {
00751 int idx;
00752 static char out_buf[sizeof(uint8_t) * sizeof(char) + 1];
00753 uint8_t btmp;
00754
00755
00756 for(idx = 0; idx < 8; idx++)
00757 {
00758
00759 btmp = ((in_byte >> (7 - idx)) & 0x01);
00760
00761 out_buf[idx] = (btmp + '0');
00762 }
00763
00764 return(out_buf);
00765 }
00766
00767
00793 int di_buf_validate(const daq_buf_t buf)
00794 {
00795 int idx;
00796
00797
00798 if((buf[0] & 0x01) != 0x00)
00799 return(1);
00800
00801
00802 for(idx = 1; idx < 8; idx++)
00803 if((buf[idx] & 0x01) != 0x01)
00804 return(idx + 1);
00805
00806 return(0);
00807 }
00808
00809
00841 int di_buf_decode(const daq_buf_t buf,
00842 daq_reading_t *result, const int NUM_BITS)
00843 {
00844 uint16_t atmp[4];
00845 int idx;
00846 double slope = 20.0 / ((double) (1 << NUM_BITS));
00847
00848 if((buf == NULL) || (result == NULL))
00849 return(-1);
00850
00851
00852 if(di_buf_validate(buf) == 0)
00853 {
00854 result->is_valid = true;
00855 }
00856 else
00857 {
00858 result->is_valid = false;
00859
00860 printf("\nSignature not found; invalid buffer: '");
00861 for(idx = 0; idx < sizeof(daq_buf_t); idx++)
00862 hex_print_byte(buf[idx]);
00863 printf("'\n");
00864 return(1);
00865 }
00866
00867
00868
00869
00870
00871
00872
00873
00874 if(NUM_BITS == 12)
00875 {
00876
00877 atmp[0] = ((buf[1] & 0xFE) << 4) | ((buf[0] & 0xF8) >> 3);
00878 atmp[1] = ((buf[3] & 0xFE) << 4) | ((buf[2] & 0xF8) >> 3);
00879 atmp[2] = ((buf[5] & 0xFE) << 4) | ((buf[4] & 0xF8) >> 3);
00880 atmp[3] = ((buf[7] & 0xFE) << 4) | ((buf[6] & 0xF8) >> 3);
00881
00882
00883 result->digital[0] = (buf[2] & 0x08) ? 1 : 0;
00884 result->digital[1] = (buf[2] & 0x04) ? 1 : 0;
00885 result->digital[2] = (buf[2] & 0x02) ? 1 : 0;
00886 }
00887 if(NUM_BITS == 10)
00888 {
00889
00890 atmp[0] = ((buf[1] & 0xFE) << 2) | ((buf[0] & 0xF0) >> 5);
00891 atmp[1] = ((buf[3] & 0xFE) << 2) | ((buf[2] & 0xF0) >> 5);
00892 atmp[2] = ((buf[5] & 0xFE) << 2) | ((buf[4] & 0xF0) >> 5);
00893 atmp[3] = ((buf[7] & 0xFE) << 2) | ((buf[6] & 0xF0) >> 5);
00894
00895
00896
00897 result->digital[0] = (buf[2] & 0x08) ? 1 : 0;
00898 result->digital[1] = (buf[2] & 0x04) ? 1 : 0;
00899 result->digital[2] = (buf[2] & 0x02) ? 1 : 0;
00900 }
00901 else if(NUM_BITS == 8)
00902 {
00903
00904 atmp[0] = (buf[1] & 0xFE) | ((buf[0] & 0xF0) >> 7);
00905 atmp[1] = (buf[3] & 0xFE) | ((buf[2] & 0xF0) >> 7);
00906 atmp[2] = (buf[5] & 0xFE) | ((buf[4] & 0xF0) >> 7);
00907 atmp[3] = (buf[7] & 0xFE) | ((buf[6] & 0xF0) >> 7);
00908
00909
00910 result->digital[0] = (buf[0] & 0x08) ? 1 : 0;
00911 result->digital[1] = (buf[0] & 0x04) ? 1 : 0;
00912 result->digital[2] = (buf[0] & 0x02) ? 1 : 0;
00913 }
00914
00915
00916 for(idx = 0; idx < 4; idx++)
00917 {
00918 result->analog[idx] = -10.0 + (slope * (atmp[idx]));
00919 result->raw[idx] = atmp[idx];
00920 }
00921
00922 return(0);
00923 }
00924
00925
00946 int di_open(const char *COMPORT_FILE, int *num_bits)
00947 {
00948 char me[] = "di_open";
00949 int rc;
00950 char *portname = NULL;
00951 const char com1[] = "/dev/ttyS0";
00952 int comm_fd = -1;
00953
00954
00955 if(COMPORT_FILE == NULL)
00956 {
00957
00958 portname = getenv("DI194_PORT");
00959 if(portname == NULL)
00960 {
00961
00962 portname = (char *) com1;
00963 }
00964 }
00965 else
00966 portname = (char *) COMPORT_FILE;
00967
00968
00969
00970
00971
00972 comm_fd = di_serial_init(portname);
00973 if(comm_fd < 0)
00974 {
00975 fprintf(stderr, "\n%s: Error opening port '%s'",
00976 me, portname);
00977 return(-1);
00978 }
00979
00980
00981
00982
00983
00984 rc = di_initialize(comm_fd, num_bits);
00985 if(rc != 0)
00986 {
00987 fprintf(stderr, "\n%s: Error initializing device\n", me);
00988 return(-2);
00989 }
00990
00991
00992
00993
00994
00995 rc = di_configure(comm_fd);
00996 if(rc != 0)
00997 {
00998 fprintf(stderr, "\n%s: Error programming device\n", me);
00999 return(-3);
01000 }
01001
01002
01003 return(comm_fd);
01004 }
01005
01006
01020 int di_close(const int COMM_FD)
01021 {
01022 char me[] = "di_close";
01023 int rc;
01024
01025 rc = di_serial_close(COMM_FD);
01026
01027 if(rc != 0)
01028 fprintf(stderr, "\n%s: Error %d closing DI-194 port\n",
01029 me, rc);
01030
01031 return(rc);
01032 }
01033
01034
01035
01054 int di_read(const int COMM_FD, daq_reading_t *data, const int NUM_BITS)
01055 {
01056 char me[] = "di_read";
01057 int rc;
01058 daq_buf_t raw_buf;
01059
01060
01061
01062 rc = di_serial_read(COMM_FD, raw_buf,
01063 sizeof(raw_buf), serial_timeout);
01064 if(rc != 0)
01065 {
01066 fprintf(stderr, "\n%s: Error %d on serial read",
01067 me, rc);
01068 return(rc);
01069 }
01070
01071
01072 rc = di_buf_decode(raw_buf, data, NUM_BITS);
01073 if(rc != 0)
01074 {
01075 fprintf(stderr, "\n%s: Error %d on buffer decode; overflow?",
01076 me, rc);
01077
01078 return(rc);
01079 }
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089 return(0);
01090 }
01091
01092
01111 int di_read_single(const int COMM_FD, daq_reading_t *data, const int NUM_BITS)
01112 {
01113 int rc;
01114
01115
01116
01117 rc = di_start(COMM_FD);
01118 if(rc != 0)
01119 return(rc);
01120
01121 rc = di_read(COMM_FD, data, NUM_BITS);
01122 if(rc != 0)
01123 {
01124 di_stop(COMM_FD);
01125 return(rc);
01126 }
01127
01128 rc = di_stop(COMM_FD);
01129
01130 return(rc);
01131 }
01132