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