/*****************************************************************************/

/*
 *      client.c  --  Transceiver control client.
 *
 *      Copyright (C) 2000, 2001
 *          Thomas Sailer (t.sailer@alumni.ethz.ch)
 *
 *      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., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 *  Please note that the GPL allows you to use the driver, NOT the radio.
 *  In order to use the radio, you need a license from the communications
 *  authority of your country.
 *
 *  History:
 *   0.1  19.09.2000  Created
 *
 */

/*****************************************************************************/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "trxapi.h"

#include <stdio.h>
#include <getopt.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>

/* --------------------------------------------------------------------- */

static unsigned int verboselevel = 0;

#if defined(WIN32)
#define UINT64_FORMAT "I64u"
#else
#define UINT64_FORMAT "llu"
#endif

/* --------------------------------------------------------------------- */

static void list_trxobjects(void)
{
	unsigned int index = 0, i;
	struct trxapi *trx;
	const struct trxapi_description *desc;
	struct trxapi_state state;

	for (;; index++) {
		if (!(trx = trxapi_open_byindex(index)))
			break;
		printf("Transceiver Index %u\n", index);
		desc = trxapi_get_description(trx);
		if (!desc) {
			printf("  trxapi_get_description error\n");
			trxapi_close(trx);
			continue;
		}
		printf("  Manufacturer           : %s\n"
		       "  Model                  : %s\n"
		       "  Copyright              : %s\n"
		       "  Instance ID (serial no): %s\n"
		       "  RSSI range             : %gdB..%gdB\n"
		       "  Receive Bands:\n",
		       desc->manufacturer, desc->model, desc->copyright, desc->instid,
		       desc->rssimin, desc->rssimax);
		for (i = 0; i < desc->nrrxbands; i++)
			printf("    Frequency range %10" UINT64_FORMAT "-%10" UINT64_FORMAT " stepsize %10" UINT64_FORMAT "\n",
			       desc->rxbands[i].low, desc->rxbands[i].high, desc->rxbands[i].step);
		printf("  Transmit Bands:\n");
		for (i = 0; i < desc->nrtxbands; i++)
			printf("    Frequency range %10" UINT64_FORMAT "-%10" UINT64_FORMAT " stepsize %10" UINT64_FORMAT "\n",
			       desc->txbands[i].low, desc->txbands[i].high, desc->txbands[i].step);
		if (trxapi_get_state(trx, &state)) {
			printf("  trxapi_get_state error\n");
			trxapi_close(trx);
			continue;
		}
		printf("  RX Frequency  : %10" UINT64_FORMAT "\n"
		       "  TX Frequency  : %10" UINT64_FORMAT "\n",
                       state.rxfreq, state.txfreq);
                printf("  PTT           : %s\n"
		       "  DCD           : %s\n"
		       "  RSSI          : %gdB\n",
		       state.ptt ? "on" : "off",
		       state.dcd ? "on" : "off", state.rssi);
		trxapi_close(trx);
	}
	if (!index)
		printf("No Transceivers found\n");
}

/* --------------------------------------------------------------------- */

static int periodic_trxstate(unsigned int index)
{
	unsigned int i;
	struct trxapi *trx;
	const struct trxapi_description *desc;
	struct trxapi_state state;

	if (!(trx = trxapi_open_byindex(index))) {
		fprintf(stderr, "Cannot find transceiver index %u\n", index);
		return 1;
	}
	printf("Transceiver Index %u\n", index);
	desc = trxapi_get_description(trx);
	if (!desc) {
		printf("  trxapi_get_description error\n");
		trxapi_close(trx);
		return 1;
	}
	printf("  Manufacturer           : %s\n"
	       "  Model                  : %s\n"
	       "  Copyright              : %s\n"
	       "  Instance ID (serial no): %s\n"
	       "  RSSI range             : %gdB..%gdB\n"
	       "  Receive Bands:\n",
	       desc->manufacturer, desc->model, desc->copyright, desc->instid,
	       desc->rssimin, desc->rssimax);
	for (i = 0; i < desc->nrrxbands; i++)
		printf("    Frequency range %10" UINT64_FORMAT "-%10" UINT64_FORMAT " stepsize %10" UINT64_FORMAT "\n",
		       desc->rxbands[i].low, desc->rxbands[i].high, desc->rxbands[i].step);
	printf("  Transmit Bands:\n");
	for (i = 0; i < desc->nrtxbands; i++)
		printf("    Frequency range %10" UINT64_FORMAT "-%10" UINT64_FORMAT " stepsize %10" UINT64_FORMAT "\n",
		       desc->txbands[i].low, desc->txbands[i].high, desc->txbands[i].step);
	for (;;) {
		if (trxapi_get_state(trx, &state)) {
			printf("  trxapi_get_state error\n");
			trxapi_close(trx);
			return 1;
		}
		printf("RX %10" UINT64_FORMAT " TX %10" UINT64_FORMAT " PTT %c DCD %c RSSI %8.2fdB\n", 
		       state.rxfreq, state.txfreq, state.ptt ? 'P' : '-',
		       state.dcd ? 'D' : '-', state.rssi);
		sleep(1);
	}
	trxapi_close(trx);
}

/* --------------------------------------------------------------------- */

static int setfreq(unsigned int index, unsigned int rx, unsigned int tx)
{
	struct trxapi *trx;

	if (!(trx = trxapi_open_byindex(index))) {
		fprintf(stderr, "Cannot find transceiver index %u\n", index);
		return 1;
	}	
	if (trxapi_set_frequency(trx, rx, tx)) {
		printf("  trxapi_set_frequency error\n");
		trxapi_close(trx);
		return 1;
	}
	trxapi_close(trx);
	return 0;
}

/* --------------------------------------------------------------------- */

static int rxuart(unsigned int index)
{
	unsigned long fifoptr = 0;
	struct trxapi *trx;
	char buf[256];
	char *cp;

	if (!(trx = trxapi_open_byindex(index))) {
		fprintf(stderr, "Cannot find transceiver index %u\n", index);
		return 1;
	}	
	for (;;) {
		if (trxapi_uart_receive(trx, &fifoptr, buf, sizeof(buf))) {
			printf("  trxapi_uart_receive error\n");
			trxapi_close(trx);
			return 1;
		}
		cp = buf;
		while ((cp = strchr(cp, '\r')))
			*cp++ = '\n';
		printf("%s", buf);
		fflush(stdout);
		sleep(1);
	}
	trxapi_close(trx);
	return 0;
}

/* --------------------------------------------------------------------- */

static int txuart(unsigned int index, const char *str)
{
	struct trxapi *trx;
	char buf[256];

	if (!(trx = trxapi_open_byindex(index))) {
		fprintf(stderr, "Cannot find transceiver index %u\n", index);
		return 1;
	}	
	snprintf(buf, sizeof(buf), "%s\r", str);
	if (trxapi_uart_send(trx, buf)) {
		printf("  trxapi_uart_send error\n");
		trxapi_close(trx);
		return 1;
	}
	trxapi_close(trx);
	return 0;
}

/* --------------------------------------------------------------------- */

static int setptt(unsigned int index, unsigned int ptt)
{
	struct trxapi *trx;

	if (!(trx = trxapi_open_byindex(index))) {
		fprintf(stderr, "Cannot find transceiver index %u\n", index);
		return 1;
	}	
	if (trxapi_set_ptt(trx, ptt)) {
		printf("  trxapi_set_ptt error\n");
		trxapi_close(trx);
		return 1;
	}
	trxapi_close(trx);
	return 0;
}

/* --------------------------------------------------------------------- */

int main (int argc, char *argv[])
{
        static const struct option long_options[] = {
		{ "list", 0, 0, 'l' },
		{ "setfreq", 0, 0, 's' },
		{ "rxuart", 0, 0, 'r' },
		{ "txuart", 0, 0, 't' },
 		{ "ptt", 0, 0, 'p' },
                { "verbose", 0, 0, 'v' },
		{ "help", 0, 0, 'h' },
                { 0, 0, 0, 0 }
        };
        int c, err = 0;
	unsigned int index = 0, mode = 0;

        printf("trxclient v" VERSION " (c) 2000 by Thomas Sailer, HB9JNX/AE4WA\n");
	/* init CORBA */
	if (trxapi_init(&argc, argv))
		exit(1);
	while ((c = getopt_long(argc, argv, "vli:srpt", long_options, NULL)) != EOF) {
                switch (c) {
                case 'v':
                        verboselevel++;
                        break;

		case 'l':
			mode = 1;
			break;

		case 's':
			mode = 2;
			break;

		case 'r':
			mode = 3;
			break;

		case 'p':
			mode = 4;
			break;

		case 't':
			mode = 5;
			break;

		case 'i':
			index = strtoul(optarg, NULL, 0);
			break;

                default:
                        err++;
                        break;
                }
        }
        if (err) {
                fprintf(stderr, "usage: %s [-v] [-l]\n", argv[0]);
		exit(1);
        }
	switch (mode) {
	default:
		exit(periodic_trxstate(index));

	case 1:
		list_trxobjects();
		exit(0);

	case 2:
		if (optind + 2 > argc) {
			fprintf(stderr, "usage: %s -s <rx> <tx>\n", argv[0]);
			exit(1);
		}
		exit(setfreq(index, strtoul(argv[optind], NULL, 0), strtoul(argv[optind+1], NULL, 0)));

	case 3:
		exit(rxuart(index));

	case 4:
		if (optind + 1 > argc) {
			fprintf(stderr, "usage: %s -s <rx> <tx>\n", argv[0]);
			exit(1);
		}
		exit(setptt(index, strtoul(argv[optind], NULL, 0)));

	case 5:
		if (optind + 1 > argc) {
			fprintf(stderr, "usage: %s -s <rx> <tx>\n", argv[0]);
			exit(1);
		}
		exit(txuart(index, argv[optind]));

	}
	return 0;
}
