/* Last modified on Sun Feb 25 2007, Hal Murray */ /* * This is a hack/demo program to test/exercise the Prologix GPIB-USB * board on a Linux system. It's what I was looking for when I * was trying to get mine going. * This is setup to talk to /dev/ttyUSB1 * Edit to match your system. * Prologix info at: http://prologix.googlepages.com/ * More GPIB info at http://www.ko4bb.com/Test_Equipment/GPIB.html * Prologix says their board goes into blink mode if you get * the baud rate wrong. It also blinks if you send another * command while it's still processing the previous one. * That can happen if you don't have the flow control setup right. * Linux kernels somewhere between 2.4.16 and 2.6.19 made a major * cleanup to the USB drivers. The flow control code was split * out into the SERIAL_GENERIC module. It wasn't getting loaded * on my system. I don't know why. I included it in the kernel * and build a new one. Before I did that, I had things working * with a 50 ms pause after sending each command. * The cruft sprinkled throughout this code is leftover from my debugging. * It's a good place to add printout if you are chasing similar problems. * I compile with: * cc -O2 -Wall -Wstrict-prototypes -Wmissing-prototypes -g -o probe probe.c * I have a HP 5334B on device address 3. * This hack is setup to read the frequency. * If you have something similar it will printout something like this. * If you are trying to get off the ground, I suggest disconnecting * all devices until you see the version string from the Prologix card. * If you have something connected, don't be surprsied * if you get some extra printout. Your device may be running * in continious mode (Single Cycle off) sending an answer occasionally. * If the answer arrives "too soon" the printout may get garbled. Flushing input.......... Here we go... << ++ver >> Prologix GPIB-USB Controller version 3.12d << ++addr 3 << ID >> HP5334B << IN >>?? << GV0 << GS1 << FN1 Got: "F +9.9999993E+06" */ char *port = "/dev/ttyUSB1"; // 1 to use hardware flow control (what Prologix expects) // 0 to try without #define FLOW 1 #include #include #include #include #include #include #include #include #include // I have an HP 5334B at this address #define ADDR 3 /* prototypes */ void SetupGPIB(void); void SendCommand(char* cmd); void SendEOL(void); char* GetAnswer(int seconds); void PrintResponse(void); int fd = -1; void SetupGPIB() { int err, i; struct termios mode; /* need NONBLOCK to avoid hanging if LOCAL flag isn't set */ /* At least on real TTYs. */ fd = open(port, O_RDWR | O_NONBLOCK); if (fd < 0) { printf("# Can't open %s: %s\n", port, strerror(errno)); sleep(10); exit(1); } /* Setup all the mode bits. Check with: stty -a -F /dev/ttyUSB1 */ err = tcgetattr(fd, &mode); if (err < 0) { printf("# tcsetattr failed: %s\n", strerror(errno)); sleep(10); exit(1); } if (0) printf("Initial modes: if: %x, of: %x, cf: %x, lf: %x\n", mode.c_iflag, mode.c_oflag, mode.c_cflag, mode.c_lflag); // printf("Before tcsetattr\n"); // sleep(10); mode.c_cflag |= CS8; // 8 data bits mode.c_cflag &= ~PARENB; // No parity mode.c_cflag &= ~CSTOPB; // 1 stop bit mode.c_cflag |= CLOCAL; if (FLOW) mode.c_cflag |= CRTSCTS; // Hardware flow control on else mode.c_cflag &= ~CRTSCTS; // Hardware flow control off cfsetispeed(&mode, B115200); cfsetospeed(&mode, B115200); mode.c_lflag &= ~ECHO; // No local echo err = tcsetattr(fd, TCSANOW, &mode); if (err < 0) { printf("# tcsetattr failed: %s\n", strerror(errno)); sleep(10); exit(1); } if (0) printf("Initial modes: if: %x, of: %x, cf: %x, lf: %x\n", mode.c_iflag, mode.c_oflag, mode.c_cflag, mode.c_lflag); // printf("After tcsetattr\n"); // sleep(10); printf("Flushing input"); for (i=0; i<10; i++) { err = tcflush(fd, TCIOFLUSH); if (err < 0) { printf("# tcflush failed: %s\n", strerror(errno)); sleep(10); exit(1); } printf("."); usleep(50000); } printf("\n"); // printf("After tcflush\n"); // sleep(1); // printf("## Opened...\n"); // sleep(10); if (!FLOW) { int bits = TIOCM_DTR | TIOCM_RTS; err = ioctl(fd, TIOCMBIS, &bits); /* Turn on DTR and RTS */ if (err < 0) { printf("# Can't set DTR: %s\n", strerror(errno)); sleep(10); exit(1); } printf("## No FLOW, Turned on DTR and RTS.\n"); } } static int lines = 0; void SendEOL() { int err; if (0) printf("## Sending EOL (%d)\n", lines++); err = write(fd, "\r\n", 2); if (err != 2) { printf("# Can't send EOL (%d): %s\n", err, strerror(errno)); sleep(10); exit(1); } if (!FLOW) usleep(50000); // Hack to avoid blink mode without flow control } void SendCommand(char* cmd) { size_t length = strlen(cmd); int err; if (0) printf("## Sending command: %s (%d)\n", cmd, length); if (1) printf("<< %s\n", cmd); err = write(fd, cmd, length); if (err != length) { printf("# Can't send command: %s\n", strerror(errno)); sleep(10); exit(1); } SendEOL(); } #define LINESIZE 1000 void PrintResponse() { int err, i, len; char line[LINESIZE+1]; for (i = 0; i < LINESIZE; i++) { err = read(fd, &line[i], 1); if (err == -1) { // try again if (i==0) usleep(100000); usleep(100000); err = read(fd, &line[i], 1); } if (err == -1) { line[i] = 0; break; } if (0) printf("i=%d, c=%c\n", i, line[i]); if (0) fflush(stdout); // Prologix normally uses \r\n. Dump \r. if (line[i] == '\r') i--; } if (i == 0) { // No response printf(">>??\n"); return; } // Chop off trailing \ns. There are normally 2 of them. for ( ; i>0; i--) { if (line[i-1] != '\n') break; line[i-1] = 0; } len = i; for (i=0; i NL at %d\n", i); } printf(">> %s\n", line); } char answer[LINESIZE+1]; char* GetAnswer(int seconds) { int err, i, len; char *line = answer; for (i = 0; i < LINESIZE; i++) { err = read(fd, &line[i], 1); if (err == -1) { // Not ready yet if ((i==0) && (seconds > 0)) { // printf("."); sleep(1); i--; seconds--; continue; } usleep(25000); err = read(fd, &line[i], 1); } if (err == -1) { line[i] = 0; break; } if (0) printf("i=%d, c=%c\n", i, line[i]); if (0) fflush(stdout); // Prologix normally uses \r\n. Dump \r. if (line[i] == '\r') i--; } if (i == 0) { // No response // printf(">>??\n"); return(NULL); } // Chop off trailing \ns in answer. There are normally 2 of them. for ( ; i>0; i--) { if (line[i-1] != '\n') break; line[i-1] = 0; } len = i; // printf(">len=%d\n", len); for (i=0; i NL at %d\n", i); } // printf(">> %s", line); return(answer); } int main(int argc, char *argv[]) { char *ans; char cmd[100]; if (argc > 1) { printf("Don't know what to do with args.\n"); sleep(10); exit(1); } SetupGPIB(); printf("Here we go...\n"); SendEOL(); SendCommand("++ver"); PrintResponse(); // I have an HP 5334B at device address 3 sprintf(cmd, "++addr %d", ADDR); SendCommand(cmd); SendCommand("ID"); // What device? (if any) PrintResponse(); SendCommand("IN"); // Initialize // PrintResponse(); no response SendCommand("GV0"); // 100 cycle average off SendCommand("GS1"); // Single cycle on SendCommand("FN1"); // Measure Frequency on Chan A ans = GetAnswer(2); if (ans) printf("Got: \"%s\"\n", ans); else printf("No answer.\n"); exit(0); }