/*
 * $RCSfile: timers.c,v $  $Revision: 1.10 $  $Name:  $
 * $Id: timers.c,v 1.10 2007/09/09 18:16:05 bpaauwe Exp $
 * $Author: bpaauwe $
 * $Date: 2007/09/09 18:16:05 $
 * ----------------------------------------------------------------------------
 *
 *  Copyright (c) Bob Paauwe (2006)
 *
 *  This program 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; either version 2 of the License, or (at your option)
 *  any later version.
 *
 *  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; if not, write to the Free Software Foundation, Inc.,
 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 *
 * ----------------------------------------------------------------------------
 *
 *  Description:
 *    A program to test timer manipulations
 *
 *    Event 0x02 0x47 0x52 0x00 - erase timers and reset tables to 1800/
 *    3000/4800
 * ----------------------------------------------------------------------------
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#include <time.h>
#include "ilib.h"
/* #include "scenes.h" */
#include "../timers.h"


#define VERSION "timer version 0.2.20a Copyright (C) 2006, Bob Paauwe"

timer_timerec_t *timers = NULL;
unsigned char cvt_days (char *days);

int alpha_to_i(char *str);
void load_timers(ilib_t *iplc, char *fname);
void clear_timers(ilib_t *iplc);
void date_test(ilib_t *iplc);
void set_alarm(ilib_t *iplc, int hour, int min);
void date_set(ilib_t *iplc);

void usage(char *prog)
{
	printf("usage: %s\n", prog);
	printf("       [-d <start addr> <length>] dump memory.\n");
	printf("       [-t] get timers.\n");
	printf("       [-l <file>] load timers from file.\n");
	printf("       [-c] clear timers.\n");
	printf("       [-s <hr> <min>] set next alarm timer.\n");
	printf("       [-x print timer stats.\n");
	printf("       [-u update PLC clock (set to PC clock).\n");
}

int main (int argc, char **argv)
{
	ilib_t *iplc;
	unsigned char test[100];
	unsigned char buffer[65536];
	int i;
	char device_id[10];
	unsigned int start_addr;
	int dump = 0;
	int timer = 0;
	char *fname = NULL;
	int clear = 0;
	int date = 0;
	int hour, min;
	int set = 0;
	int update = 0;

	memset(device_id, 0, 10);

	if (argc > 0) {
		for (i = 1; i < argc; i++) {
			if (argv[i][0] == '-') {
				switch (argv[i][1]) {
					case 'v':
						printf("%s\n", VERSION);

						printf("arg = %d\n", alpha_to_i(argv[++i]));
						return 0;
						break;
					case 'h':
						usage(argv[0]);
						return 0;
						break;
					case 'd': /* do memory dump */
						dump = 1;
						start_addr = alpha_to_i(argv[++i]);
						dump = atoi(argv[++i]);
						break;
					case 's': /* Set next alarm time */
						set = 1;
						hour = atoi(argv[++i]);
						min = atoi(argv[++i]);
						break;
					case 't': /* dump timers */
						timer = 1;
						break;
					case 'c': /* clear timers */
						clear = 1;
						break;
					case 'x': /* date time test */
						date = 1;
						break;
					case 'u': /* date time update */
						update = 1;
						break;
					case 'l': /* load timers */
						fname = argv[++i];
						break;
					default:
						usage(argv[0]);
						return 0;
						break;
				}
			}
		}
	}

	if ((iplc = ilib_open(USE_HIDDEV, "/dev/hiddev0")) == NULL) {
	/*if ((iplc = ilib_open(USE_IPLC, "/dev/usb/iplc0")) == NULL) {
		if ((iplc = ilib_open(USE_LIBUSB, NULL)) == NULL) {
			if ((iplc = ilib_open(USE_LIBHID, NULL)) == NULL) {
				printf("Failed to connect to PLC.\n");
				return -1;
			}
		}
		*/
		printf("Failed to connect to PLC.\n");
		return -1;
	}

	/* Send some test commands */
	if (ibios_get_version(iplc, &test[0], buffer) == 0) {
		printf("PLC ID: %s   Firmware version %02x\n", buffer, test[0]);
	} else {
		printf("Command failed\n");
	}

	/* Do what the command line args tell us to do */

	if(dump) {
		printf("Dump %d bytes starting at 0x%04x\n", dump, start_addr);
		ibios_read_memory(iplc, start_addr, dump, buffer);
		for (i = 0; i < dump; i++) {
			if ((i % 16) == 0) {
				printf("\n0x%04x: ", (start_addr + i));
			}
			printf("%02x ", (buffer[i] & 0xff));
		}
		printf("\n");
	}

	if (timer) {
		print_timer_record(get_timer_info(iplc));
	}

	if (clear) {
		clear_timers(iplc);
	}

	if (date) {
		date_test(iplc);
	}

	if (update) {
		date_set(iplc);
	}

	if (set) {
		set_alarm(iplc, hour, min);
	}

	if (fname) {
		load_timers(iplc, fname);
	}

	ilib_close(iplc);
	return 0;
}


/*
 * date_test
 *
 * Dump data in readable format about PLC date and time
 */
void date_test(ilib_t *iplc)
{
	unsigned char buffer[29];
	unsigned short minutes;
	unsigned short timer;

	/* ibios_timer_refresh(iplc); */

	ibios_read_memory(iplc, 0x0158, 9, buffer);

	minutes = (buffer[0] << 8) | buffer[1];
	printf("%d minutes past midnight\n", minutes);
	printf("%02d/%02d/%02d %02d:%02d:%02d\n", buffer[3], buffer[4],
			buffer[2], buffer[6], buffer[7], buffer[8]);

	ibios_read_memory(iplc, 0x0033, 1, buffer);
	printf("Timer buffer end = 0x%02x\n", buffer[0]);

	ibios_read_memory(iplc, 0x0040, 20, buffer);
	timer = (buffer[0] << 8) | buffer[1];
	printf("Time of day alarm: %d minutes past midnight\n", timer);

	timer = (buffer[6] << 8) | buffer[7];
	printf("timer 1: %d minutes past midnight\n", timer);
	timer = (buffer[8] << 8) | buffer[9];
	printf("timer 2: %d minutes past midnight\n", timer);
	timer = (buffer[10] << 8) | buffer[11];
	printf("timer 3: %d minutes past midnight\n", timer);
	timer = (buffer[12] << 8) | buffer[13];
	printf("timer 4: %d minutes past midnight\n", timer);

	return;
}


/*
 * date_set
 *
 * Set the PLC's real time clock
 */
void date_set(ilib_t *iplc)
{
	unsigned char buffer[30];
	time_t tm;
	struct tm *lt;
	int dow;

	ibios_read_memory(iplc, 0x015a, 6, buffer);

	printf("%02d/%02d/%02d %02d:%02d:%02d (%02x)\n", buffer[1], buffer[2],
			buffer[0], buffer[4], buffer[5], buffer[6], buffer[3]);

	time(&tm);
	lt = localtime(&tm);

	/* Put current time into buffer */
	buffer[0] = (lt->tm_year - 100);
	buffer[1] = lt->tm_mon + 1;
	buffer[2] = lt->tm_mday;
	buffer[4] = lt->tm_hour;
	buffer[5] = lt->tm_min;
	buffer[6] = lt->tm_sec;
	if (lt->tm_wday == 0) {
		dow = 6;
	} else {
		dow = lt->tm_wday - 1;
	}

	buffer[3] = 1 << dow;

	ibios_write_memory(iplc, 0x015a, 6, buffer);

	ibios_read_memory(iplc, 0x015a, 6, buffer);

	printf("%02d/%02d/%02d %02d:%02d:%02d (%02x)\n", buffer[1], buffer[2],
			buffer[0], buffer[4], buffer[5], buffer[6], buffer[3]);
}

void set_alarm(ilib_t *iplc, int hour, int min)
{
	unsigned char buffer[29];
	unsigned short minutes;

	minutes = (hour * 60) + min;
	buffer[0] = (minutes >> 8) & 0xff;
	buffer[1] = minutes & 0xff;
	ibios_write_memory(iplc, 0x0046, 2, buffer);

	buffer[0] = 0x18;
	buffer[1] = 0x00;
	ibios_write_memory(iplc, 0x0054, 2, buffer);
}
