diff pathloss/main.c @ 65:b3f04535eb14

pathloss: initial code, no distance calculation yet
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 25 Oct 2024 07:42:53 +0000
parents
children 599fac1b882d
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pathloss/main.c	Fri Oct 25 07:42:53 2024 +0000
@@ -0,0 +1,274 @@
+/*
+ * This program reads a file of input parameters for a GSM radio link
+ * and computes maximum reach distances per several common models.
+ */
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+#define	MAX_FIELDS	5
+static char linebuf[256], *fields[MAX_FIELDS];
+static unsigned nfields;
+
+static float freq_dl, freq_ul;
+static float bts_power, bts_rxs, bts_ant_gain;
+static float ms_power, ms_rxs;
+static int band_set, bts_param_set, ms_param_set;
+
+static float bts_height, ms_height;
+static int bts_height_set, ms_height_set;
+
+static float misc_loss;
+
+static void
+parse_into_fields(filename, lineno)
+	char *filename;
+{
+	char *cp;
+
+	nfields = 0;
+	for (cp = linebuf; ; ) {
+		while (isspace(*cp))
+			cp++;
+		if (*cp == '\0' || *cp == '#')
+			break;
+		if (nfields >= MAX_FIELDS) {
+			fprintf(stderr, "%s line %d: too many fields\n",
+				filename, lineno);
+			exit(1);
+		}
+		fields[nfields++] = cp;
+		while (*cp && !isspace(*cp))
+			cp++;
+		if (*cp)
+			*cp++ = '\0';
+	}
+}
+
+static void
+set_band(filename, lineno)
+	char *filename;
+{
+	if (nfields != 2) {
+		fprintf(stderr, "%s line %d: band setting takes 1 argument\n",
+			filename, lineno);
+		exit(1);
+	}
+	if (!strcasecmp(fields[1], "PCS")) {
+		freq_dl = 1990.0f;
+		freq_ul = 1910.0f;
+	} else if (!strcasecmp(fields[1], "B5")) {
+		freq_dl = 894.0f;
+		freq_ul = 849.0f;
+	} else if (!strcasecmp(fields[1], "ISM")) {
+		freq_dl = 925.2f;
+		freq_ul = 880.2f;
+	} else {
+		fprintf(stderr, "%s line %d: unknown band name \"%s\"\n",
+			filename, lineno, fields[1]);
+		exit(1);
+	}
+	band_set = 1;
+}
+
+static void
+set_bts_param(filename, lineno)
+	char *filename;
+{
+	if (nfields != 4) {
+		fprintf(stderr,
+			"%s line %d: bts-param setting takes 3 arguments\n",
+			filename, lineno);
+		exit(1);
+	}
+	bts_power = atof(fields[1]);
+	bts_rxs = atof(fields[2]);
+	bts_ant_gain = atof(fields[3]);
+	bts_param_set = 1;
+}
+
+static void
+set_bts_height(filename, lineno)
+	char *filename;
+{
+	float val, mult;
+
+	if (nfields != 3) {
+		fprintf(stderr,
+			"%s line %d: bts-height setting takes 2 arguments\n",
+			filename, lineno);
+		exit(1);
+	}
+	val = atof(fields[1]);
+	if (!strcmp(fields[2], "m"))
+		mult = 1.0f;
+	else if (!strcmp(fields[2], "ft"))
+		mult = 0.3048f;
+	else {
+		fprintf(stderr,
+			"%s line %d: height unit must be either m or ft\n",
+			filename, lineno);
+		exit(1);
+	}
+	bts_height = val * mult;
+	bts_height_set = 1;
+}
+
+static void
+set_ms_param(filename, lineno)
+	char *filename;
+{
+	if (nfields != 3) {
+		fprintf(stderr,
+			"%s line %d: ms-param setting takes 2 arguments\n",
+			filename, lineno);
+		exit(1);
+	}
+	ms_power = atof(fields[1]);
+	ms_rxs = atof(fields[2]);
+	ms_param_set = 1;
+}
+
+static void
+set_ms_height(filename, lineno)
+	char *filename;
+{
+	float val, mult;
+
+	if (nfields != 3) {
+		fprintf(stderr,
+			"%s line %d: ms-height setting takes 2 arguments\n",
+			filename, lineno);
+		exit(1);
+	}
+	val = atof(fields[1]);
+	if (!strcmp(fields[2], "m"))
+		mult = 1.0f;
+	else if (!strcmp(fields[2], "ft"))
+		mult = 0.3048f;
+	else {
+		fprintf(stderr,
+			"%s line %d: height unit must be either m or ft\n",
+			filename, lineno);
+		exit(1);
+	}
+	ms_height = val * mult;
+	ms_height_set = 1;
+}
+
+static void
+add_loss_line(filename, lineno)
+	char *filename;
+{
+	float val;
+
+	if (nfields != 2) {
+		fprintf(stderr, "%s line %d: loss setting takes 1 argument\n",
+			filename, lineno);
+		exit(1);
+	}
+	val = atof(fields[1]);
+	misc_loss += val;
+}
+
+static void
+process_line(filename, lineno)
+	char *filename;
+{
+	if (!strcmp(fields[0], "band"))
+		set_band(filename, lineno);
+	else if (!strcmp(fields[0], "bts-param"))
+		set_bts_param(filename, lineno);
+	else if (!strcmp(fields[0], "bts-height"))
+		set_bts_height(filename, lineno);
+	else if (!strcmp(fields[0], "ms-param"))
+		set_ms_param(filename, lineno);
+	else if (!strcmp(fields[0], "ms-height"))
+		set_ms_height(filename, lineno);
+	else if (!strcmp(fields[0], "loss"))
+		add_loss_line(filename, lineno);
+	else {
+		fprintf(stderr, "%s line %d: non-understood setting \"%s\"\n",
+			filename, lineno, fields[0]);
+		exit(1);
+	}
+}
+
+static void
+check_required_params(filename)
+	char *filename;
+{
+	if (!band_set) {
+		fprintf(stderr, "error: %s failed to set band\n", filename);
+		exit(1);
+	}
+	if (!bts_param_set) {
+		fprintf(stderr, "error: %s failed to set bts-param\n",
+			filename);
+		exit(1);
+	}
+	if (!bts_height_set) {
+		fprintf(stderr, "error: %s failed to set bts-height\n",
+			filename);
+		exit(1);
+	}
+	if (!ms_param_set) {
+		fprintf(stderr, "error: %s failed to set ms-param\n", filename);
+		exit(1);
+	}
+	if (!ms_height_set) {
+		fprintf(stderr, "error: %s failed to set ms-height\n",
+			filename);
+		exit(1);
+	}
+}
+
+static void
+read_param_file(filename)
+	char *filename;
+{
+	FILE *inf;
+	int lineno;
+
+	inf = fopen(filename, "r");
+	if (!inf) {
+		perror(filename);
+		exit(1);
+	}
+	for (lineno = 1; fgets(linebuf, sizeof linebuf, inf); lineno++) {
+		if (!index(linebuf, '\n')) {
+			fprintf(stderr,
+				"%s line %d: too long or missing newline\n",
+				filename, lineno);
+			exit(1);
+		}
+		parse_into_fields(filename, lineno);
+		if (nfields == 0)
+			continue;
+		process_line(filename, lineno);
+	}
+	fclose(inf);
+	check_required_params(filename);
+}
+
+main(argc, argv)
+	char **argv;
+{
+	float path_loss_dl, path_loss_ul;
+
+	if (argc != 2) {
+		fprintf(stderr, "usage: %s param-file\n", argv[0]);
+		exit(1);
+	}
+	read_param_file(argv[1]);
+	/* do the math */
+	path_loss_dl = bts_power + bts_ant_gain - ms_rxs - misc_loss;
+	path_loss_ul = ms_power + bts_ant_gain - bts_rxs - misc_loss;
+	printf("Path loss budget: %.2f dB DL, %.2f dB UL\n", path_loss_dl,
+		path_loss_ul);
+	/* distance calculations will go here */
+	exit(0);
+}