From 867e9530360a9243d05f53990837fa44baea467e Mon Sep 17 00:00:00 2001 From: Maurizio Porrato Date: Sat, 1 Dec 2018 12:20:36 +0000 Subject: [PATCH] New UT61E serial port tool --- tools/.gitignore | 6 ++ tools/Makefile | 13 +++ tools/frame-parser.c | 126 +++++++++++++++++++++++ {samples/ut61e => tools}/frame-parser.py | 0 tools/ut61e-ser.c | 110 ++++++++++++++++++++ 5 files changed, 255 insertions(+) create mode 100644 tools/.gitignore create mode 100644 tools/Makefile create mode 100644 tools/frame-parser.c rename {samples/ut61e => tools}/frame-parser.py (100%) create mode 100644 tools/ut61e-ser.c diff --git a/tools/.gitignore b/tools/.gitignore new file mode 100644 index 0000000..b0103d0 --- /dev/null +++ b/tools/.gitignore @@ -0,0 +1,6 @@ +*~ +*% +*.swp +core +frame-parser +ut61e-ser diff --git a/tools/Makefile b/tools/Makefile new file mode 100644 index 0000000..e7db1b4 --- /dev/null +++ b/tools/Makefile @@ -0,0 +1,13 @@ +.PHONY: all clean + +CC=gcc +CFLAGS=-std=c1x -Wall -pedantic -pipe + +BIN=frame-parser ut61e-ser + +all: $(BIN) + +frame-parser: LDFLAGS+=-lm + +clean: + -rm -f $(BIN) diff --git a/tools/frame-parser.c b/tools/frame-parser.c new file mode 100644 index 0000000..bf3aeb1 --- /dev/null +++ b/tools/frame-parser.c @@ -0,0 +1,126 @@ +#include +#include +#include +#include + +struct packet_s { + char range; + char digits[5]; + char function; + char status; + char options[4]; + char eol[2]; + char eos; +}; + +enum unit_e { + U_UNKNOWN = 0, + U_VOLTAGE, + U_CURRENT, + U_RESISTANCE, + U_FREQUENCY, + U_CAPACITANCE, + U_ADP // ??? +}; + +struct range_entry_s { + uint8_t divider; // Where to place the decimal point + int8_t exponent; // 0->Unit 3->KUnit 6->MUnit -3->mUnit -6->uUnit ... +}; + +char *units[] = { "?", "V", "A", "Ohm", "Hz", "F", "?" }; + +enum unit_e function_unit[] = { + U_CURRENT, // 22A + U_VOLTAGE, // Diode + U_FREQUENCY, + U_RESISTANCE, + U_UNKNOWN, // Temperature + U_RESISTANCE, // Continuity + U_CAPACITANCE, + U_UNKNOWN, + U_UNKNOWN, + U_CURRENT, // Manual current + U_UNKNOWN, + U_VOLTAGE, + U_UNKNOWN, + U_CURRENT, // Auto uA + U_UNKNOWN, // ADP + U_CURRENT // Auto mA +}; + +struct range_entry_s ranges[8][16] = { + // 22A Diode Freq Resist Temp Cont Capac ? ? Man A ? V ? Auto uA ADP Auto mA + { { 3, 0 }, { 4, 0 }, { 2, 0 }, { 2, 0 }, { 0, 0 }, { 2, 0 }, { 3, -9}, { 0, 0 }, { 0, 0 }, { 4, 0 }, { 0, 0 }, { 4, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { { 0, 0 }, { 0, 0 }, { 1, 0 }, { 4, 3 }, { 0, 0 }, { 0, 0 }, { 2, -9}, { 0, 0 }, { 0, 0 }, { 3, 0 }, { 0, 0 }, { 3, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { { 0, 0 }, { 0, 0 }, { 0, 0 }, { 3, 3 }, { 0, 0 }, { 0, 0 }, { 4, -6}, { 0, 0 }, { 0, 0 }, { 2, 0 }, { 0, 0 }, { 2, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { { 0, 0 }, { 0, 0 }, { 3, 3 }, { 2, 3 }, { 0, 0 }, { 0, 0 }, { 3, -6}, { 0, 0 }, { 0, 0 }, { 1, 0 }, { 0, 0 }, { 1, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { { 0, 0 }, { 0, 0 }, { 2, 3 }, { 4, 6 }, { 0, 0 }, { 0, 0 }, { 2, -6}, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 2, -3}, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { { 0, 0 }, { 0, 0 }, { 4, 6 }, { 3, 6 }, { 0, 0 }, { 0, 0 }, { 4, -3}, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { { 0, 0 }, { 0, 0 }, { 3, 6 }, { 2, 6 }, { 0, 0 }, { 0, 0 }, { 3, -3}, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } }, + { { 0, 0 }, { 0, 0 }, { 2, 6 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 2, -3}, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 }, { 0, 0 } } +}; + +int parse_packet(struct packet_s *packet) { + int32_t number; + double reading; + int i; + int range, function; + struct range_entry_s re; + + for (number = 0, i = 0; i < sizeof(packet->digits); i++) { + number *= 10; + number += packet->digits[i] & 0x0f; + } + + printf("%6d <- %s", number, (char *)packet); + + range = packet->range & 0x07; + function = packet->function & 0x0f; + + re = ranges[range][function]; + + if ((re.divider == 0) && (re.exponent == 0)) { + printf("Invalid function/range combo: f=%x r=%x\n", function, range); + } + + reading = number * pow(10.0, re.exponent - re.divider); + + printf("Reading = %lf %s\n", reading, units[function_unit[function]]); + + return 0; +} + +int read_packet(struct packet_s *packet) { + char *r; + int i; + int valid; + + while (1) { + r = fgets((char *)packet, sizeof(*packet), stdin); + if (r == NULL) + return 0; + // Sanity checks + // Packet must end with CR+LF + if (packet->eol[0] != '\r' || packet->eol[1] != '\n') + continue; + // All fields must be encoded as 0x3X + for (valid=1, i=0; i +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define SER_SPEED B19200 +#define SER_BITS CS7 +#define SER_PARITY (PARENB | PARODD) + +int quit_flag = 0; + +void handle_sigint(int a) { + quit_flag = 1; +} + +int sercat(char *dev) { + int fd; + struct termios tty, orig_tty; + int tio, orig_tio; + int r; + char buffer[14]; + + signal(SIGINT, handle_sigint); + + fd = open(dev, O_RDWR | O_NOCTTY); + if (fd < 0) { + perror("open():"); + return fd; + } + + memset(&orig_tty, 0, sizeof(orig_tty)); + + r = tcgetattr(fd, &orig_tty); + if (r < 0) { + close(fd); + perror("tcgetattr():"); + return r; + } + + memcpy(&tty, &orig_tty, sizeof(orig_tty)); + + cfsetospeed(&tty, SER_SPEED); + cfsetispeed(&tty, SER_SPEED); + + tty.c_cflag = (tty.c_cflag & ~CSIZE) | SER_BITS; + + tty.c_cflag = (tty.c_cflag & ~(PARENB | PARODD)) | SER_PARITY; + + tty.c_cflag &= ~CSTOPB; + tty.c_cflag &= ~CRTSCTS; + + tty.c_iflag &= ~ICRNL; + + r = tcsetattr(fd, TCSANOW, &tty); + if (r < 0) { + perror("tcsetattr():"); + close(fd); + return r; + } + + ioctl(fd, TIOCMGET, &orig_tio); + + // To power the adapter we need DTR high and RTS low + tio = (orig_tio & ~TIOCM_RTS) | TIOCM_DTR; + + ioctl(fd, TIOCMSET, &tio); + + while ((r = read(fd, buffer, sizeof(buffer))) > 0) { + write(STDOUT_FILENO, buffer, r); + if (quit_flag) + break; + } + + close(STDOUT_FILENO); + + if (r < 0) { + perror("read():"); + } + + r = tcsetattr(fd, TCSANOW, &orig_tty); + if (r < 0) { + perror("tcsetattr(restore):"); + } + + ioctl(fd, TIOCMSET, &orig_tio); + + close(fd); + return 0; +} + +void usage(char *bin) { + fprintf(stderr, "Symtax: %s SERIAL_PORT\n", bin); +} + +int main(int argc, char *argp[]) { + if (argc < 2) + usage(argp[0]); + else { + if (sercat(argp[1]) < 0) + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +}