New UT61E serial port tool
This commit is contained in:
parent
4a88b0ecda
commit
867e953036
|
@ -0,0 +1,6 @@
|
||||||
|
*~
|
||||||
|
*%
|
||||||
|
*.swp
|
||||||
|
core
|
||||||
|
frame-parser
|
||||||
|
ut61e-ser
|
|
@ -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)
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
Loading…
Reference in New Issue