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);
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 tcgetattr(comm_fd ,&term);
00104
00105
00106 term.c_cflag &= ~CSIZE;
00107 term.c_cflag |= CS8;
00108 term.c_cflag |= HUPCL;
00109 term.c_cflag |= CREAD;
00110 term.c_cflag &= ~CRTSCTS;
00111 term.c_cflag |= IXON;
00112
00113
00114 term.c_oflag &= ~OPOST;
00115
00116
00117 term.c_iflag = IGNBRK|IGNPAR;
00118
00119
00120 term.c_lflag = 0;
00121
00122
00123 term.c_cc[VMIN] = 0;
00124 term.c_cc[VTIME] = (serial_timeout * 10);
00125
00126
00127 cfsetispeed(&term, baud_rate);
00128 cfsetospeed(&term, baud_rate);
00129
00130
00131 tcsetattr(comm_fd, TCSANOW, &term);
00132
00133
00134 usleep(25000);
00135
00136
00137 cfsetispeed(&term, B0);
00138 cfsetospeed(&term, B0);
00139 tcsetattr(comm_fd, TCSANOW, &term);
00140
00141
00142 cfsetospeed(&term, baud_rate);
00143 tcsetattr(comm_fd, TCSANOW, &term);
00144
00145
00146 usleep(25000);
00147
00148
00149 tcflush(comm_fd, TCIOFLUSH);
00150
00151 return(comm_fd);
00152 }
00153
00154
00171 int min(const int A, const int B)
00172 {
00173 return(A < B? A : B);
00174 }
00175
00176
00187 void hex_print_byte(const uint8_t in_byte)
00188 {
00189 printf("%02X ", (int) in_byte);
00190 if(isprint(in_byte))
00191 printf("(%c)", in_byte);
00192 }
00193
00194 int di_stop(const int COMM_FD)
00195 {
00196 return(di_cmd_send(COMM_FD, stop_cmd, sizeof(stop_cmd)));
00197 }
00198
00199
00200 int di_start(const int COMM_FD)
00201 {
00202 return(di_cmd_send(COMM_FD, start_cmd, sizeof(start_cmd)));
00203 }
00204
00205 int di_reset(const int COMM_FD)
00206 {
00207 return(di_cmd_send(COMM_FD, rst_cmd, sizeof(rst_cmd)));
00208 }
00209
00210 int di_serial_num(const int COMM_FD, char *ser_buf)
00211 {
00212 char me[] = "di_serial";
00213 int rc, idx;
00214
00215 rc = di_cmd_send(COMM_FD, sn_cmd, sizeof(sn_cmd));
00216 if(rc != 0)
00217 {
00218 fprintf(stderr,
00219 "\nError sending serial number request, rc=%d\n", rc);
00220 return(1);
00221 }
00222
00223
00224 rc = di_serial_read(COMM_FD, ser_buf, SERIAL_NUM_LEN, serial_timeout);
00225 if(rc != 0)
00226 {
00227
00228 fprintf(stderr, "\n%s: Error reading serial number", me);
00229
00230 if(rc >= 1)
00231 {
00232 fprintf(stderr, "\n%s: Data received was '", me);
00233 for(idx = 0; idx < rc; idx++)
00234 fprintf(stderr, "%02X ",
00235 (int) ser_buf[idx]);
00236 fprintf(stderr, "'\n");
00237 }
00238 return(2);
00239 }
00240
00241 return(0);
00242 }
00243
00244
00245
00266 int di_serial_read(const int COMM_FD, const uint8_t *buf,
00267 const int READ_LEN, const time_t TIMEOUT)
00268 {
00269 char me[] = "di_serial_read";
00270 time_t t_start;
00271 int rc;
00272 int rx_count = 0;
00273
00274 t_start = time(NULL);
00275
00276
00277 while(((time(NULL) - t_start) < TIMEOUT) &&
00278 (rx_count < READ_LEN))
00279 {
00280
00281 rc = read(COMM_FD, (uint8_t *) &buf[rx_count],
00282 (READ_LEN - rx_count));
00283 if(rc < 0)
00284 {
00285
00286 fprintf(stderr, "\n%s: Error on read, rc=%d", me, rc);
00287 return(1);
00288 }
00289 if(rc == 0)
00290 {
00291
00292 usleep(100);
00293 }
00294 else
00295 rx_count += rc;
00296 }
00297
00298
00299 if(rx_count >= READ_LEN)
00300 return(0);
00301 else
00302 {
00303 fprintf(stderr, "\n%s: Short read, got %d of %d expected",
00304 me, rx_count, READ_LEN);
00305 fprintf(stderr, ", elapsed was %u seconds",
00306 (uint32_t) (time(NULL) - t_start));
00307
00308 if(rx_count != 0)
00309 return(rx_count);
00310 else
00311 return(-1);
00312 }
00313 }
00314
00315
00324 void di_cmd_print(const uint8_t *cmd, const int CMD_LEN)
00325 {
00326 char me[] = "di_cmd_print";
00327 int idx;
00328
00329 if(CMD_LEN > 1)
00330 fprintf(stderr, "\n%s: %d-byte command '", me, CMD_LEN);
00331 else if(CMD_LEN == 1)
00332 fprintf(stderr, "\n%s: 1-byte argument '", me);
00333 else
00334 {
00335 fprintf(stderr, "\n%s: Error, invalid cmd length %d",
00336 me, CMD_LEN);
00337 return;
00338 }
00339
00340 for(idx = 0; idx < CMD_LEN; idx++)
00341 {
00342 fprintf(stderr, " %02X", (int) cmd[idx]);
00343
00344 if(isprint(cmd[idx]))
00345 fprintf(stderr, " (%c)", cmd[idx]);
00346 }
00347
00348 fprintf(stderr, "'");
00349 return;
00350 }
00351
00352
00375 bool is_reset_cmd(const uint8_t *cmd, const int CMD_LEN)
00376 {
00377 char me[] = "is_reset_cmd";
00378 int idx;
00379
00380
00381 if((CMD_LEN != 3) || (cmd == NULL))
00382 return(false);
00383
00384 for(idx = 0; idx < CMD_LEN; idx++)
00385 if(cmd[idx] != rst_cmd[idx])
00386 return(false);
00387
00388 return(true);
00389
00390
00391 fprintf(stderr, "\n%s: Reset command found", me);
00392 }
00393
00394
00417 int di_daq_sync(const int COMM_FD)
00418 {
00419 char me[] = "di_daq_sync";
00420 uint8_t sync_buf[5 * sizeof(daq_buf_t)] = "";
00421 int idx, rc, clear_count;
00422 bool found_match = false;
00423
00424
00425
00426 rc = di_serial_read(COMM_FD, sync_buf, (4 * sizeof(daq_buf_t)),
00427 serial_timeout);
00428 if(rc != 0)
00429 {
00430 fprintf(stderr, "\n%s: Error reading\n", me);
00431 return(rc);
00432 }
00433
00434
00435 for(idx = 0; idx < (3 * sizeof(daq_buf_t)); idx++)
00436 {
00437 rc = di_buf_validate(&sync_buf[idx]);
00438 if(rc != 0)
00439 fprintf(stderr, "\n%s: No sync at index %d, rc %d", me, idx, rc);
00440 else
00441 {
00442
00443 found_match = true;
00444 break;
00445 }
00446 }
00447
00448 if(found_match == true)
00449 {
00450
00451 clear_count = idx;
00452
00453 rc = di_serial_read(COMM_FD, sync_buf,
00454 clear_count, serial_timeout);
00455 if(rc != 0)
00456 {
00457 fprintf(stderr, "\n%s: Error on sync read!", me);
00458 return(rc);
00459 }
00460
00461
00462 return(0);
00463 }
00464 else
00465 fprintf(stderr, "\nNo sync\n");
00466
00467
00468 return(-1);
00469 }
00470
00471
00472
00502 int di_cmd_send(const int COMM_FD, const uint8_t *cmd, const int CMD_LEN)
00503 {
00504 char me[] = "di_cmd_send";
00505 int idx, rc;
00506 uint8_t btmp;
00507 int read_len = CMD_LEN;
00508
00509 if(cmd == NULL)
00510 return(-1);
00511
00512
00513
00514
00515
00516
00517
00518
00519 for(idx = 0; idx < CMD_LEN; idx++)
00520 {
00521
00522 rc = write(COMM_FD, &cmd[idx], sizeof(uint8_t));
00523 if(rc != sizeof(uint8_t))
00524 {
00525 fprintf(stderr, "\n%s: Error sending command", me);
00526 return(1);
00527 }
00528
00529
00530 if(cmd[idx] == 0x00)
00531 continue;
00532
00533
00534 rc = di_serial_read(COMM_FD, &btmp,
00535 sizeof(btmp), serial_timeout);
00536 if(rc != 0)
00537 {
00538 fprintf(stderr, "\n%s: Error on command echo read",
00539 me);
00540 return(2);
00541 }
00542
00543 if(btmp != cmd[idx])
00544 {
00545 fprintf(stderr, "\n%s: Cmd was %02X, echo was %02X",
00546 me, (int) cmd[idx], (int) btmp);
00547 }
00548
00549
00550
00551
00552
00553 }
00554
00555
00556 for(idx = 0; idx < (read_len - CMD_LEN); idx++)
00557 {
00558 rc = di_serial_read(COMM_FD, &btmp,
00559 sizeof(btmp), serial_timeout);
00560 if(rc != 0)
00561 {
00562 fprintf(stderr, "\n%s: Error reading trailer bytes\n",
00563 me);
00564 }
00565 }
00566
00567 return(0);
00568 }
00569
00570
00589 int di_initialize(const int COMM_FD, int *num_bits)
00590 {
00591 char me[] = "di_initialize";
00592 int idx, rc;
00593 uint8_t ser_buf[SERIAL_NUM_LEN * 2] = "";
00594 const uint8_t rs_signature[SERIAL_NUM_LEN + 1] = "0000000000";
00595
00596
00597
00598 read(COMM_FD, ser_buf, 1);
00599
00600
00601 di_cmd_send(COMM_FD, odd_cmd, sizeof(odd_cmd));
00602
00603
00604 rc = di_stop(COMM_FD);
00605
00606
00607 rc = di_serial_num(COMM_FD, ser_buf);
00608 if(rc != 0)
00609 return(rc);
00610
00611
00612 if(strncmp(ser_buf, rs_signature, SERIAL_NUM_LEN) == 0)
00613 {
00614 printf("\nNew (RS) unit found, skipping enable code download");
00615 *num_bits = 10;
00616 }
00617 else
00618 {
00619 *num_bits = 8;
00620 printf("\nDI-194 found, Serial number: '");
00621
00622 for(idx = 0; idx < SERIAL_NUM_LEN; idx++)
00623 printf("%c", ser_buf[idx]);
00624 printf("'\nSending enable key to device");
00625
00626
00627
00628 for(idx = 0; idx < sizeof(di_enable_key); idx++)
00629 {
00630 rc = di_cmd_send(COMM_FD, key_cmd, sizeof(key_cmd));
00631 if(rc != 0)
00632 {
00633 fprintf(stderr, "\n%s: Error sending key command", me);
00634 return(2);
00635 }
00636
00637
00638 rc = di_cmd_send(COMM_FD, &di_enable_key[idx], sizeof(uint8_t));
00639 if(rc != 0)
00640 {
00641 fprintf(stderr, "\n%s: Error sending key byte", me);
00642 return(2);
00643 }
00644 }
00645 }
00646
00647 return(0);
00648 }
00649
00650
00651
00676 int di_configure(const int COMM_FD)
00677 {
00678 char me[] = "di_configure";
00679 int rc;
00680
00681 if(COMM_FD <= 0)
00682 {
00683 fprintf(stderr, "\n%s: Invalid file descriptor %d",
00684 me, COMM_FD);
00685 return(1);
00686 }
00687
00688
00689 rc = di_cmd_send(COMM_FD, all_chan, sizeof(all_chan));
00690 if(rc != 0)
00691 {
00692 fprintf(stderr, "\n%s: Error sending all-channels command",
00693 me);
00694 return(2);
00695 }
00696
00697
00698 rc = di_cmd_send(COMM_FD, dig_chan, sizeof(dig_chan));
00699 if(rc != 0)
00700 {
00701 fprintf(stderr,
00702 "\n%s: Error sending digital channels command", me);
00703 return(2);
00704 }
00705
00706
00707 return(0);
00708 }
00709
00710
00726 char *di_byte_print(const uint8_t in_byte)
00727 {
00728 int idx;
00729 static char out_buf[sizeof(uint8_t) * sizeof(char) + 1];
00730 uint8_t btmp;
00731
00732
00733 for(idx = 0; idx < 8; idx++)
00734 {
00735
00736 btmp = ((in_byte >> (7 - idx)) & 0x01);
00737
00738 out_buf[idx] = (btmp + '0');
00739 }
00740
00741 return(out_buf);
00742 }
00743
00744
00770 int di_buf_validate(const daq_buf_t buf)
00771 {
00772 int idx;
00773
00774
00775 if((buf[0] & 0x01) != 0x00)
00776 return(1);
00777
00778
00779 for(idx = 1; idx < 8; idx++)
00780 if((buf[idx] & 0x01) != 0x01)
00781 return(idx + 1);
00782
00783 return(0);
00784 }
00785
00786
00818 int di_buf_decode(const daq_buf_t buf,
00819 daq_reading_t *result, const int NUM_BITS)
00820 {
00821 uint16_t atmp[4];
00822 int idx;
00823 double slope = 20.0 / ((double) (1 << NUM_BITS));
00824
00825 if((buf == NULL) || (result == NULL))
00826 return(-1);
00827
00828
00829 if(di_buf_validate(buf) == 0)
00830 {
00831 result->is_valid = true;
00832 }
00833 else
00834 {
00835 result->is_valid = false;
00836
00837 printf("\nSignature not found; invalid buffer: '");
00838 for(idx = 0; idx < sizeof(daq_buf_t); idx++)
00839 hex_print_byte(buf[idx]);
00840 printf("'\n");
00841 return(1);
00842 }
00843
00844
00845
00846
00847
00848
00849
00850
00851 if(NUM_BITS == 10)
00852 {
00853 atmp[0] = (((buf[1] & 0xFE) << 8) | ((buf[0] & 0xF0) >> 5)) >> 6;
00854 atmp[1] = (((buf[3] & 0xFE) << 8) | ((buf[2] & 0xF0) >> 5)) >> 6;
00855 atmp[2] = (((buf[5] & 0xFE) << 8) | ((buf[4] & 0xF0) >> 5)) >> 6;
00856 atmp[3] = (((buf[7] & 0xFE) << 8) | ((buf[6] & 0xF0) >> 5)) >> 6;
00857
00858 for(idx = 0; idx < 4; idx++)
00859 {
00860 result->analog[idx] = -10.0 + (slope * (atmp[idx]));
00861 result->raw[idx] = atmp[idx];
00862 }
00863
00864
00865
00866 result->digital[0] = (buf[2] & 0x08) ? 1 : 0;
00867 result->digital[1] = (buf[2] & 0x04) ? 1 : 0;
00868 result->digital[2] = (buf[2] & 0x02) ? 1 : 0;
00869
00870 }
00871 else if(NUM_BITS == 8)
00872 {
00873 atmp[0] = (((buf[1] & 0xFE) << 8) | ((buf[0] & 0xF0) >> 7)) >> 8;
00874 atmp[1] = (((buf[3] & 0xFE) << 8) | ((buf[2] & 0xF0) >> 7)) >> 8;
00875 atmp[2] = (((buf[5] & 0xFE) << 8) | ((buf[4] & 0xF0) >> 7)) >> 8;
00876 atmp[3] = (((buf[7] & 0xFE) << 8) | ((buf[6] & 0xF0) >> 7)) >> 8;
00877
00878 for(idx = 0; idx < 4; idx++)
00879 {
00880 result->analog[idx] = -10.0 + (slope * (atmp[idx]));
00881 result->raw[idx] = atmp[idx];
00882 }
00883
00884
00885
00886 result->digital[0] = (buf[0] & 0x08) ? 1 : 0;
00887 result->digital[1] = (buf[0] & 0x04) ? 1 : 0;
00888 result->digital[2] = (buf[0] & 0x02) ? 1 : 0;
00889 }
00890
00891 return(0);
00892 }
00893
00894
00914 int di_open(const char *COMPORT_FILE, int *num_bits)
00915 {
00916 char me[] = "di_open";
00917 int rc;
00918 char *portname = NULL;
00919 const char com1[] = "/dev/ttyS0";
00920 int comm_fd = -1;
00921
00922
00923 if(COMPORT_FILE == NULL)
00924 {
00925
00926 portname = getenv("DI194_PORT");
00927 if(portname == NULL)
00928 {
00929
00930 portname = (char *) com1;
00931 }
00932 }
00933 else
00934 portname = (char *) COMPORT_FILE;
00935
00936
00937
00938
00939
00940 comm_fd = di_serial_init(portname);
00941 if(comm_fd < 0)
00942 {
00943 fprintf(stderr, "\n%s: Error opening port '%s'",
00944 me, portname);
00945 return(-1);
00946 }
00947
00948
00949
00950
00951
00952 rc = di_initialize(comm_fd, num_bits);
00953 if(rc != 0)
00954 {
00955 fprintf(stderr, "\n%s: Error initializing device\n", me);
00956 return(-2);
00957 }
00958
00959
00960
00961
00962
00963 rc = di_configure(comm_fd);
00964 if(rc != 0)
00965 {
00966 fprintf(stderr, "\n%s: Error programming device\n", me);
00967 return(-3);
00968 }
00969
00970
00971 return(comm_fd);
00972 }
00973
00974
00988 int di_close(const int COMM_FD)
00989 {
00990 char me[] = "di_close";
00991 int rc;
00992
00993 rc = di_serial_close(COMM_FD);
00994
00995 if(rc != 0)
00996 fprintf(stderr, "\n%s: Error %d closing DI-194 port\n",
00997 me, rc);
00998
00999 return(rc);
01000 }
01001
01002
01003
01021 int di_read(const int COMM_FD, daq_reading_t *data, const int NUM_BITS)
01022 {
01023 char me[] = "di_read";
01024 int rc;
01025 daq_buf_t raw_buf;
01026
01027
01028
01029 rc = di_serial_read(COMM_FD, raw_buf,
01030 sizeof(raw_buf), serial_timeout);
01031 if(rc != 0)
01032 {
01033 fprintf(stderr, "\n%s: Error %d on serial read",
01034 me, rc);
01035 return(rc);
01036 }
01037
01038
01039 rc = di_buf_decode(raw_buf, data, NUM_BITS);
01040 if(rc != 0)
01041 {
01042 fprintf(stderr, "\n%s: Error %d on buffer decode; overflow?",
01043 me, rc);
01044
01045 return(rc);
01046 }
01047
01048
01049
01050
01051
01052
01053
01054
01055
01056 return(0);
01057 }
01058
01059
01077 int di_read_single(const int COMM_FD, daq_reading_t *data, const int NUM_BITS)
01078 {
01079 int rc;
01080
01081
01082
01083 rc = di_start(COMM_FD);
01084 if(rc != 0)
01085 return(rc);
01086
01087 rc = di_read(COMM_FD, data, NUM_BITS);
01088 if(rc != 0)
01089 {
01090 di_stop(COMM_FD);
01091 return(rc);
01092 }
01093
01094 rc = di_stop(COMM_FD);
01095
01096 return(rc);
01097 }
01098