view librftab/rftablerd.c @ 587:5b88ba62b9ae

doc/Rvinterf-tools: rvinterf -P option documented
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 03 Feb 2020 07:56:57 +0000
parents a0f79bba0ad8
children 059649902c7f
line wrap: on
line source

/*
 * Reading RF tables from formatted ASCII files: used for the rftw command
 * in fc-tmsh, for the upload-rf-table command in fc-fsio, and in the
 * standalone fc-cal2bin utility.
 */

#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include "../rvinterf/include/exitcodes.h"

#include "rdcommon.c"

static char *format;
static u_char *writeptr;
static unsigned written_size, maxsize;

static
process_number(size)
{
	char *field;
	int rc;
	u_long number;

	rc = get_field(&field);
	if (rc < 0)
		return(ERROR_USAGE);
	if (!rc) {
		printf("error: %s is too short for table format %s\n",
			filename, format);
		return(ERROR_USAGE);
	}
	if (field[0] == '-')
		number = strtol(field, 0, 0);
	else
		number = strtoul(field, 0, 0);
	switch (size) {
	case 1:
		*writeptr++ = number;
		break;
	case 2:
		*writeptr++ = number;
		*writeptr++ = number >> 8;
		break;
	case 4:
		*writeptr++ = number;
		*writeptr++ = number >> 8;
		*writeptr++ = number >> 16;
		*writeptr++ = number >> 24;
		break;
	default:
		abort();
	}
	written_size += size;
	return(0);
}

static
expect_keyword(kw)
	char *kw;
{
	char *field;
	int rc;

	rc = get_field(&field);
	if (rc < 0)
		return(ERROR_USAGE);
	if (!rc) {
		printf("error: %s is too short for table format %s\n",
			filename, format);
		return(ERROR_USAGE);
	}
	if (strcmp(field, kw)) {
		printf("%s line %d: expected %s keyword\n", filename, lineno,
			kw);
		return(ERROR_USAGE);
	}
	return(0);
}

static
ensure_eof()
{
	char *field;
	int rc;

	rc = get_field(&field);
	if (rc < 0)
		return(ERROR_USAGE);
	if (rc) {
		printf("error: %s is too long for table format %s\n",
			filename, format);
		return(ERROR_USAGE);
	}
	return(0);
}

static
read_agc_table()
{
	int i, rc;

	for (i = 0; i < 20; i++) {
		rc = process_number(2);
		if (rc)
			return(rc);
	}
	return ensure_eof();
}

static
read_afcparams()
{
	int i, rc;

	for (i = 0; i < 4; i++) {
		rc = process_number(4);
		if (rc)
			return(rc);
	}
	for (i = 0; i < 4; i++) {
		rc = process_number(2);
		if (rc)
			return(rc);
	}
	return ensure_eof();
}

static
read_agc_global_params()
{
	int i, rc;

	for (i = 0; i < 4; i++) {
		rc = process_number(2);
		if (rc)
			return(rc);
	}
	return ensure_eof();
}

static
read_il2agc()
{
	int i, rc;

	for (i = 0; i < 121; i++) {
		rc = process_number(1);
		if (rc)
			return(rc);
	}
	return ensure_eof();
}

static
read_tx_ramps()
{
	int i, j, rc;

	if (maxsize < 512) {
		printf("error: tx-ramps table not allowed in this context\n");
		return(ERROR_USAGE);
	}
	for (i = 0; i < 16; i++) {
		rc = expect_keyword("ramp-up");
		if (rc)
			return(rc);
		for (j = 0; j < 16; j++) {
			rc = process_number(1);
			if (rc)
				return(rc);
		}
		rc = expect_keyword("ramp-down");
		if (rc)
			return(rc);
		for (j = 0; j < 16; j++) {
			rc = process_number(1);
			if (rc)
				return(rc);
		}
	}
	return ensure_eof();
}

static
read_tx_levels()
{
	int i, rc;

	for (i = 0; i < 32; i++) {
		rc = process_number(2);
		if (rc)
			return(rc);
		rc = process_number(1);
		if (rc)
			return(rc);
		rc = process_number(1);
		if (rc)
			return(rc);
	}
	return ensure_eof();
}

static
read_tx_calchan()
{
	int i, rc;

	for (i = 0; i < 64; i++) {
		rc = process_number(2);
		if (rc)
			return(rc);
	}
	return ensure_eof();
}

static
read_tx_caltemp()
{
	int i, rc;

	for (i = 0; i < 20; i++) {
		rc = process_number(2);
		if (rc)
			return(rc);
	}
	return ensure_eof();
}

static
read_rx_calchan()
{
	int i, rc;

	for (i = 0; i < 20; i++) {
		rc = process_number(2);
		if (rc)
			return(rc);
	}
	return ensure_eof();
}

static
read_rx_caltemp()
{
	int i, rc;

	for (i = 0; i < 22; i++) {
		rc = process_number(2);
		if (rc)
			return(rc);
	}
	return ensure_eof();
}

static
read_rx_agc_params()
{
	int i, rc;

	for (i = 0; i < 4; i++) {
		rc = process_number(2);
		if (rc)
			return(rc);
	}
	return ensure_eof();
}

static
read_raw_table()
{
	int rc;
	char *field;
	u_long number;

	for (;;) {
		rc = get_field(&field);
		if (rc < 0)
			return(ERROR_USAGE);
		if (!rc)
			break;
		number = strtoul(field, 0, 16);
		if (written_size >= maxsize) {
			printf("error: raw table %s exceeds maximum size\n",
				filename);
			return(ERROR_USAGE);
		}
		*writeptr++ = number;
		written_size++;
	}
	if (!written_size) {
		printf("error: raw table %s is empty\n", filename);
		return(ERROR_USAGE);
	}
	return(0);
}

static struct table_format {
	char *kw;
	int (*handler)();
} table_formats[] = {
	{"agc-table", read_agc_table},
	{"afcparams", read_afcparams},
	{"agc-global-params", read_agc_global_params},
	{"il2agc", read_il2agc},
	{"tx-ramps", read_tx_ramps},
	{"tx-levels", read_tx_levels},
	{"tx-calchan", read_tx_calchan},
	{"tx-caltemp", read_tx_caltemp},
	{"rx-calchan", read_rx_calchan},
	{"rx-caltemp", read_rx_caltemp},
	{"rx-agc-params", read_rx_agc_params},
	{"raw", read_raw_table},
	{0, 0}
};

read_rf_table_ext(filename_arg, rdbuf, allow_large, format_ret, size_ret)
	char *filename_arg;
	u_char *rdbuf;
	char **format_ret;
	unsigned *size_ret;
{
	char *field;
	int rc;
	struct table_format *tp;

	filename = filename_arg;
	rdfile = fopen(filename, "r");
	if (!rdfile) {
		perror(filename);
		return(ERROR_UNIX);
	}
	lineno = 0;
	line_nfields = 0;
	rc = get_field(&field);
	if (rc <= 0) {
not_valid_rftable:
		printf("error: %s is not a valid RF table file\n", filename);
		fclose(rdfile);
		return(ERROR_USAGE);
	}
	if (strcmp(field, "rf_table"))
		goto not_valid_rftable;
	rc = get_field(&field);
	if (rc <= 0)
		goto not_valid_rftable;
	for (tp = table_formats; tp->kw; tp++)
		if (!strcmp(tp->kw, field))
			break;
	if (!tp->kw) {
		printf("error: table format \"%s\" not recognized\n", field);
		fclose(rdfile);
		return(ERROR_USAGE);
	}
	format = tp->kw;
	if (format_ret)
		*format_ret = format;
	writeptr = rdbuf;
	written_size = 0;
	if (allow_large)
		maxsize = 512;
	else
		maxsize = 128;
	rc = tp->handler();
	fclose(rdfile);
	if (size_ret)
		*size_ret = written_size;
	return(rc);
}