/*
 * sartorius - Sartorius balance demonstration program for Linux
 * Copyright © 2005 by Hans Schou.
 * License: BSD
 *
 * The devices tested:
 *   Name       Model   Equiv    Capacity  Readability  Production year
 *   Sartorius  1702    CP224S    200g     0.1 mg       1985 - 1985
 *   Sartorius  BL1500  TE12101  1500g     0.1 g        1998
 * http://sartorius.balances.com/sartorius/sartorius+cross+reference.html
 *
 * For further reading:
 * http://www.glue.umd.edu/~nsw/ench485/ad/balance.for
 * http://en.tldp.org/HOWTO/Serial-Programming-HOWTO/
 * http://www.sartorius.com/
 *
 *
 * Commands on BL 1500:
 *  \eP    Print weigt
 *  \eS    Reset
 *  \eW    ?? setup pcs count ??
 */

/*
Example of output:

$ ./sartorius /dev/tts/0
Trying to open device: /dev/tts/0
Device '/dev/tts/0' open with handle '3'.
Waiting for responce from device.
Read 16 bytes: '+     23.1 g  MJ'
Restore termios and close.

*/

#include <stdio.h>
#include <ctype.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <termios.h>
#include <errno.h>
#include <string.h>

void printbuf(char *buf, int count)
{
	int i = 0;

	while (i<count) {
		if (isprint(buf[i])) {
			printf("%c", buf[i]);
		} else {
			/* Print unprintable characters in blue */
			printf("\e[34m%c\e[0m", buf[i] | '@');
		}
		i++;
	}
}

int main(int argc, char **argv)
{
	char buffer[64];
	struct termios term, term_orig;
	int fd;
	int num;

	if (argc < 2) {
		printf("Usage:\n");
		printf("\t%s <device>\n", argv[0]);
		printf("Example:\n");
		printf("\t%s /dev/tts/0\n", argv[0]);
		printf("\t%s /dev/ttyS0\n", argv[0]);
		return 1;
	}

	printf("Trying to open device: %s\n", argv[1]);
	if ((fd = open(argv[1], O_RDWR | O_NOCTTY )) > 0) {
		printf("Device '%s' open with handle '%d'.\n", argv[1], fd);

		/* Delay for open device. It take some time. */
		sleep(1);

		/* Setup: Do not act on ISIG (Ctrl-C), don't convert CR/NL and so on. */
		ioctl(fd, TCGETS, &term);
		term_orig = term;
		/* 1200 baud, 7 data bits, 1 stop bit, odd parity, hardware flow control */
		term.c_cflag = B1200 | CRTSCTS | CS7 | CSTOPB | PARENB | PARODD | CLOCAL | CREAD;
		term.c_lflag &= ~( ICANON | ISIG | ECHO );
		term.c_iflag &= ~( ICRNL );
		term.c_oflag &= ~( OPOST | ONLCR );
		ioctl(fd, TCSETS, &term);

		/* Read one sample with the Escape-P command */
		if (write(fd, "\eP", 2)) {
			printf("Waiting for responce from device.\n");
			usleep(200000);
			num = read(fd, &buffer, sizeof(buffer));
			if (num) {
				printf("Read %d bytes: '", num);
				printbuf((char *)&buffer, num);
				printf("'\n");
			}
		}

		printf("Restore termios and close.\n");
		ioctl(fd, TCSETS, &term_orig);
		close(fd);
	} else {
		fprintf(stderr, "Error on opening '%s': %s\n", argv[1], strerror(errno));
	}

	return 0;
}
