New UT61E serial port tool

This commit is contained in:
Maurizio Porrato 2018-12-01 12:20:36 +00:00
parent 4a88b0ecda
commit 867e953036
5 changed files with 255 additions and 0 deletions

6
tools/.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
*~
*%
*.swp
core
frame-parser
ut61e-ser

13
tools/Makefile Normal file
View File

@ -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)

126
tools/frame-parser.c Normal file
View File

@ -0,0 +1,126 @@
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <math.h>
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<sizeof(*packet)-4; i++)
if ((r[i] & 0xf0) != 0x30)
valid = 0;
// Should also check for valid BCD values for digits
if (valid)
return 1;
}
}
int main() {
struct packet_s packet;
while (read_packet(&packet)) {
parse_packet(&packet);
}
return EXIT_SUCCESS;
}

110
tools/ut61e-ser.c Normal file
View File

@ -0,0 +1,110 @@
#define _DEFAULT_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <signal.h>
#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;
}