// // comraw1 -- Serial port data logger for data bursts. // // - Mostly used to capture screen dumps from Tek scopes. // // 19-Nov-2001 Tom Van Baak (tvb) www.LeapSecond.com/tools // #include #include #include #include char *a0; void comm_open (int port, int baud); int comm_read (char *buf, int size); void comm_close (void); char *format_elapsed_time (long seconds); int main (int argc, char *argv[]) { FILE *log_file; char *path; int port, baud; time_t time_start; long total_bytes; a0 = argv[1]; if (argc <= 1) { fprintf(stderr, "Usage: %s [port] [baud] [logfile]\n", a0); exit(1); } port = (argc > 1) ? atoi(argv[1]) : 1; baud = (argc > 2) ? atoi(argv[2]) : 9600; path = (argc > 3) ? argv[3] : "log.dat"; log_file = fopen(path, "wb"); if (log_file == NULL) { fprintf(stderr, "%s: output log file open failed: %s\n", a0, path); exit(1); } printf("Output: %s\n", path); comm_open(port, baud); // Wait for first byte and then read all bytes until the stream stops. total_bytes = 0; time_start = time(NULL); while (1) { char iobuf[5000]; int read_count; // Note: blocking read with 1 second timeout. read_count = comm_read(iobuf, sizeof iobuf); if (read_count > 0) { fwrite(iobuf, read_count, 1, log_file); fflush(log_file); } // Step 1 - still waiting for first byte. if (total_bytes == 0 && read_count == 0) { time_t dt = time(NULL) - time_start; printf("\rIdle for %s \r", format_elapsed_time(dt)); } // Step 2 - first byte. if (total_bytes == 0 && read_count > 0) { printf("\nReading "); time_start = time(NULL); } // Step 3 - serial transfer in progress. if (total_bytes > 0 && read_count > 0) { printf("+"); } // Step 4 - serial transfer finsished. if (total_bytes > 0 && read_count == 0) { time_t dt = time(NULL) - time_start; printf("\n%Total %ld bytes", total_bytes); if (dt != 0) { printf(" (%ld seconds, %ld bytes/sec)", dt, total_bytes / dt); } printf("\n"); break; } total_bytes += read_count; } fclose(log_file); comm_close(); return 0; } // Format elapsed time in user-friendly manner. char *format_elapsed_time (long seconds) { int days, hours, minutes; static char buf[20]; // STATIC days = seconds / 86400; seconds %= 86400; hours = seconds / 3600; seconds %= 3600; minutes = seconds / 60; seconds %= 60; if (days != 0) { sprintf(buf, "%dd %dh", days, hours); } else if (hours != 0) { sprintf(buf, "%dh %dm", hours, minutes); } else { sprintf(buf, "%dm %ds", minutes, seconds); } return buf; // STATIC } // Windows-specific code. #define WIN32_LEAN_AND_MEAN #include HANDLE hCom; void comm_open (int port, int baud) { char PortPath[20]; DCB Dcb; BOOL Success; COMMTIMEOUTS Cto; sprintf(PortPath, "\\\\.\\COM%d", port); printf("Opening %s\n", PortPath); hCom = CreateFile(PortPath, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if (hCom == INVALID_HANDLE_VALUE) { fprintf(stderr, "%s: CreateFile failed: %s (%.8x)\n", a0, PortPath, GetLastError()); exit(1); } // Set up Dcb for hardware handshake. memset(&Dcb, 0x0, sizeof(DCB)); Dcb.DCBlength = sizeof (DCB); Success = GetCommState(hCom, &Dcb); if (!Success) { fprintf(stderr, "%s: GetCommState failed (%.8x)\n", a0, GetLastError()); exit(1); } Dcb.BaudRate = baud; Dcb.fBinary = TRUE; Dcb.fOutxCtsFlow = FALSE; Dcb.fOutxDsrFlow = FALSE; Dcb.fDtrControl = DTR_CONTROL_HANDSHAKE; Dcb.fDsrSensitivity = 0; Dcb.fTXContinueOnXoff = FALSE; Dcb.fOutX = FALSE; Dcb.fInX = FALSE; Dcb.fErrorChar = FALSE; Dcb.fNull = FALSE; Dcb.fRtsControl = RTS_CONTROL_HANDSHAKE; Dcb.fAbortOnError = FALSE; Dcb.ByteSize = 8; Dcb.Parity = NOPARITY; Dcb.StopBits = ONESTOPBIT; Success = SetCommState(hCom, &Dcb); if (!Success) { fprintf(stderr, "%s: SetCommState failed (%.8x)\n", a0, GetLastError()); exit(1); } // Set timeouts. Success = GetCommTimeouts(hCom, &Cto); if (!Success) { fprintf(stderr, "%s: GetCommTimeouts failed (%.8x)\n", a0, GetLastError()); exit(1); } #define TO_SECONDS 1 Cto.ReadIntervalTimeout = 0; Cto.ReadTotalTimeoutMultiplier = 0; Cto.ReadTotalTimeoutConstant = TO_SECONDS * 1000L; Success = SetCommTimeouts(hCom, &Cto); if (!Success) { fprintf(stderr, "%s: SetCommTimeouts failed (%.8x)\n", a0, GetLastError()); exit(1); } SetupComm(hCom, 10240, 10240); } int comm_read (char *buf, int size) { DWORD n; ReadFile(hCom, buf, size, &n, 0); return n; } void comm_close (void) { CloseHandle(hCom); }