FreeCalypso > hg > gsm-net-reveng
view pathloss/main.c @ 68:0cfea66a15f3
pathloss: implement Egli model
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 25 Oct 2024 16:09:52 +0000 |
parents | 599fac1b882d |
children |
line wrap: on
line source
/* * 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> #include "range_func.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 per various models */ printf("FSL: %.2f m DL, %.2f m UL\n", rf_range_freespace(freq_dl, path_loss_dl), rf_range_freespace(freq_ul, path_loss_ul)); printf("Egli: %.2f m DL, %.2f m UL\n", rf_range_egli(freq_dl, path_loss_dl, bts_height, ms_height), rf_range_egli(freq_ul, path_loss_ul, bts_height, ms_height)); /* Hata model coming next */ exit(0); }