/*
 *	extech - Program for controlling the extech Device
 *	This file is part of PowerTOP
 *
 *      Based on earlier client by Patrick Mochel for Wattsup Pro device
 *	Copyright (c) 2005 Patrick Mochel
 *	Copyright (c) 2006 Intel Corporation
 *	Copyright (c) 2011 Intel Corporation
 *
 *	Authors:
 *	    Patrick Mochel
 *	    Venkatesh Pallipadi
 *	    Arjan van de Ven
 *
 *	Thanks to Rajiv Kapoor for finding out the DTR, RTS line bits issue below
 *	Without that this program would never work.
 *
 *
 *	This program file is free software; you can redistribute it and/or modify it
 *	under the terms of the GNU General Public License as published by the
 *	Free Software Foundation; version 2 of the License.
 *
 *	This program is distributed in the hope that it will be useful, but WITHOUT
 *	ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 *	FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 *	for more details.
 *
 *	You should have received a copy of the GNU General Public License
 *	along with this program in a file named COPYING; if not, write to the
 *	Free Software Foundation, Inc,
 *	51 Franklin Street, Fifth Floor,
 *	Boston, MA 02110-1301 USA
 *	or just google for it.
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>
#include <ctype.h>
#include <getopt.h>
#include <time.h>
#include <signal.h>

#include <sys/types.h>
#include <sys/ioctl.h>

#include <sys/stat.h>

#include "measurement.h"
#include "extech.h"
#include <iostream>
#include <fstream>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

using namespace std;

struct packet {
	char	buf[256];
	char	op[32];
	double	watts;
	int	len;
};


static int open_device(const char *device_name)
{
	struct stat s;
	int ret;

	ret = stat(device_name, &s);
	if (ret < 0)
		return -1;

	if (!S_ISCHR(s.st_mode))
		return -1;

	ret = access(device_name, R_OK | W_OK);
	if (ret)
		return -1;

	ret = open(device_name, O_RDWR | O_NONBLOCK | O_NOCTTY);
	if (ret < 0)
		return -1;

	return ret;
}


static int setup_serial_device(int dev_fd)
{
	struct termios t;
	int ret;
	int flgs;

	ret = tcgetattr(dev_fd, &t);
	if (ret)
		return ret;

	cfmakeraw(&t);
	cfsetispeed(&t, B9600);
	cfsetospeed(&t, B9600);
	tcflush(dev_fd, TCIFLUSH);

	t.c_iflag = IGNPAR;
	t.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
	t.c_oflag = 0;
	t.c_lflag = 0;
	t.c_cc[VMIN] = 2;
	t.c_cc[VTIME] = 0;

	t.c_iflag &= ~(IXON | IXOFF | IXANY);
	t.c_oflag &= ~(IXON | IXOFF | IXANY);

	ret = tcsetattr(dev_fd, TCSANOW, &t);

	if (ret)
		return ret;

	/*
	 * Root caused by Rajiv Kapoor. Without this extech reads
	 * will fail
	 */

	/* get DTR and RTS line bits settings */
	ioctl(dev_fd, TIOCMGET, &flgs);

	/* set DTR to 1 and RTS to 0 */
	flgs |= TIOCM_DTR;
	flgs &= ~TIOCM_RTS;
	ioctl(dev_fd, TIOCMSET, &flgs);

	return 0;
}


static unsigned int decode_extech_value(unsigned char byt3, unsigned char byt4, char *a)
{
	unsigned int input = ((unsigned int)byt4 << 8) + byt3;
	unsigned int i;
	unsigned int idx;
	unsigned char revnum[] = { 0x0, 0x8, 0x4, 0xc,
				   0x2, 0xa, 0x6, 0xe,
				   0x1, 0x9, 0x5, 0xd,
				   0x3, 0xb, 0x7, 0xf};
	unsigned char revdec[] = { 0x0, 0x2, 0x1, 0x3};

	unsigned int digit_map[] = {0x2, 0x3c, 0x3c0, 0x3c00};
	unsigned int digit_shift[] = {1, 2, 6, 10};

	unsigned int sign;
	unsigned int decimal;

	/* this is basically BCD encoded floating point... but kinda weird */

	decimal = (input & 0xc000) >> 14;
	decimal = revdec[decimal];

	sign = input & 0x1;

	idx = 0;
	if (sign)
		a[idx++] = '+';
	else
		a[idx++] = '-';

	/* first digit is only one or zero */
	a[idx] = '0';
	if ((input & digit_map[0]) >> digit_shift[0])
		a[idx] += 1;

	idx++;
	/* Reverse the remaining three digits and store in the array */
	for (i = 1; i < 4; i++) {
		int dig = ((input & digit_map[i]) >> digit_shift[i]);
		dig = revnum[dig];
		if (dig > 0xa)
			goto error_exit;

		a[idx++] = '0' + dig;
	}

	/* Fit the decimal point where appropriate */
	for (i = 0; i < decimal; i++)
		a[idx - i] = a[idx - i - 1];

	a[idx - decimal] = '.';
	a[++idx] = '0';
	a[++idx] = '\0';

	return 0;
error_exit:
	return -1;
}

static int parse_packet(struct packet * p)
{
	int i;
	int ret;

	p->buf[p->len] = '\0';

	/*
	 * First character in 5 character block should be '02'
	 * Fifth character in 5 character block should be '03'
	 */
	for (i = 0; i < 4; i++) {
		if (p->buf[i * 0] != 2 || p->buf[i * 0 + 4] != 3) {
			printf("Invalid packet\n");
			return -1;
		}
	}

	for (i = 0; i < 1; i++) {
		ret = decode_extech_value(p->buf[5 * i + 2],
					  p->buf[5 * i + 3],
					  &(p->op[8 * i]));
		if (ret) {
			printf("Invalid packet, conversion failed\n");
			return -1;
		}
		p->watts = strtod( &(p->op[8 * i]), NULL);
	}
	return 0;
}


static double extech_read(int fd)
{
	struct packet p;
	fd_set read_fd;
	struct timeval tv;
	int ret;

	if (fd < 0)
		return 0.0;

	FD_ZERO(&read_fd);
	FD_SET(fd, &read_fd);

	tv.tv_sec = 0;
	tv.tv_usec = 500000;

	memset(&p, 0, sizeof(p));

	ret = select(fd + 1, &read_fd, NULL, NULL, &tv);
	if (ret <= 0)
		return -1;

	ret = read(fd, &p.buf, 250);
	if (ret < 0)
		return ret;
	p.len = ret;

	if (!parse_packet(&p))
		return p.watts;

	return -1000.0;
}

extech_power_meter::extech_power_meter(const char *extech_name)
{
	rate = 0.0;
	strncpy(dev_name, extech_name, sizeof(dev_name));
	int ret;

	fd = open_device(dev_name);
	if (fd < 0)
		return;

	ret = setup_serial_device(fd);
	if (ret) {
		close(fd);
		fd = -1;
		return;
	}
}


void extech_power_meter::measure(void)
{
	/* trigger the extech to send data */
	write(fd, " ", 1);

	rate = extech_read(fd);

}

void extech_power_meter::sample(void) 
{
	ssize_t ret;
	struct timespec tv;

	tv.tv_sec = 0;
	tv.tv_nsec = 200000000;
	while (!end_thread) {
		nanosleep(&tv, NULL);
		/* trigger the extech to send data */
		ret = write(fd, " ", 1);
		if (ret < 0)
			continue;
		
		sum += extech_read(fd);
		samples++;
	
	}
}

extern "C"
{
	void* thread_proc(void *arg) 
	{
		class extech_power_meter *parent;
		parent = (class extech_power_meter*)arg;
		parent->sample();
		return 0;
	}
}

void extech_power_meter::end_measurement(void)
{
	end_thread = 1;
	pthread_join( thread, NULL);
	if (samples){
		rate = sum / samples;
	}
	else
		measure();
}

void extech_power_meter::start_measurement(void)
{
	end_thread = 0;
	sum = samples = 0;
	
	if (pthread_create(&thread, NULL, thread_proc, this))
		fprintf(stderr, "ERROR: extech measurement thread creation failed\n");

}


double extech_power_meter::joules_consumed(void)
{
	return rate;
}
