From 3dcb7b34df407869dd1713cb43498b298069ad05 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sun, 14 Nov 2021 15:53:23 +0100 Subject: [PATCH] Implementation of selective call for classic German 'Sirenensteuerung' --- .gitignore | 1 + README | 2 + configure.ac | 1 + docs/index.html | 5 + docs/standard_r2000_by_jolly.pdf | Bin 60086 -> 68555 bytes src/Makefile.am | 1 + src/fuenf/Makefile.am | 51 +++ src/fuenf/dsp.c | 646 +++++++++++++++++++++++++++++++ src/fuenf/dsp.h | 5 + src/fuenf/fuenf.c | 414 ++++++++++++++++++++ src/fuenf/fuenf.h | 100 +++++ src/fuenf/image.c | 24 ++ src/fuenf/main.c | 269 +++++++++++++ src/libdebug/debug.c | 1 + src/libdebug/debug.h | 65 ++-- 15 files changed, 1553 insertions(+), 32 deletions(-) create mode 100644 src/fuenf/Makefile.am create mode 100644 src/fuenf/dsp.c create mode 100644 src/fuenf/dsp.h create mode 100644 src/fuenf/fuenf.c create mode 100644 src/fuenf/fuenf.h create mode 100644 src/fuenf/image.c create mode 100644 src/fuenf/main.c diff --git a/.gitignore b/.gitignore index 383bec8d..05d15bc8 100644 --- a/.gitignore +++ b/.gitignore @@ -71,6 +71,7 @@ src/mpt1327/mpt1327 src/jolly/jollycom src/eurosignal/eurosignal src/pocsag/pocsag +src/fuenf/5-ton-folge src/tv/osmotv src/radio/osmoradio src/datenklo/datenklo diff --git a/README b/README index 7c5a3796..474650ff 100644 --- a/README +++ b/README @@ -16,6 +16,7 @@ generated simultaniously using SDR. Currently supported networks: * IMTS / MTS ((Improved) Mobile Telephone Service) * MPT1327 (Trunked Radio) aka known as 'Buendelfunk' * Eurosignal (ERuRD paging service) + * 5-Ton-Folge (ZVEI 5 tone paging code for pager and siren trigger) * JollyCom (Unofficial network, invented by the author) * C-Netz BSC (Connecting to a C-Netz Base Station) @@ -26,6 +27,7 @@ Additionally the following communication services are implemented: * Analog Modem Emulation (AM7911) * German classic 'Zeitansage' (talking clock) * POCSAG transmitter / receiver + * 5-Ton-Folge + Sirenensteuerung USE AT YOUR OWN RISK! diff --git a/configure.ac b/configure.ac index ddc29cc7..e82f821d 100644 --- a/configure.ac +++ b/configure.ac @@ -106,6 +106,7 @@ AC_OUTPUT( src/jolly/Makefile src/eurosignal/Makefile src/pocsag/Makefile + src/fuenf/Makefile src/tv/Makefile src/radio/Makefile src/datenklo/Makefile diff --git a/docs/index.html b/docs/index.html index a89074fd..5e96f7a5 100644 --- a/docs/index.html +++ b/docs/index.html @@ -80,6 +80,10 @@ Please go to project's hompage at h Thanx to Laf0rge, there is a mailing list: https://lists.osmocom.org/mailman/listinfo/osmocom-analog.

+

+If you have questions, then write to: jolly@eversberg.eu +

+

General information:

@@ -126,6 +130,7 @@ Additional features:
  • Zeitansage (German talking clock)
  • C-Netz FuVSt (MSC to control a real base station)
  • POCSAG
  • +
  • 5-Ton-Ruf (firefighter's pagers and siren control)
  • diff --git a/docs/standard_r2000_by_jolly.pdf b/docs/standard_r2000_by_jolly.pdf index ffb6870baa3cd11a525d44e31ec92deeaa801c0c..713d7020a0942ac100574e7781a93a91a3dc2c9c 100644 GIT binary patch delta 56053 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⋘uN`%NR_E1rN0$xU@qEVf8fp)G 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 W*KCbVfD$wm3Pi%eabHP_ + * All Rights Reserved + * + * 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 3 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, see . + */ + +#define CHAN fuenf->sender.kanal + +#include +#include +#include +#include +#include +#include +#include "../libsample/sample.h" +#include "../libdebug/debug.h" +#include "../libmobile/call.h" +#include "fuenf.h" +#include "dsp.h" + +#define MAX_DISPLAY 1.4 /* something above speech level, no emphasis */ +#define MAX_MODULATION 3000.0 /* maximum bandwidth of audio signal */ + +/* TX and RX parameters */ +#define TONE_LEVEL 0.5 /* because we have two tones, also applies to digits */ + +/* TX parameters */ +#define TX_LEN_PREAMBLE 0.600 /* duration of preamble */ +#define TX_LEN_PAUSE 0.600 /* duration of pause */ +#define TX_LEN_POSTAMBLE 0.070 /* duration of postamble */ +#define TX_LEN_DIGIT 0.070 /* duration of paging tone */ +#define TX_NUM_KANAL 10 /* number of 'Kanalbelegungston' */ +#define TX_LEN_KANAL 0.250 /* duration of 'Kanalbelegungston' */ +#define TX_LEN_KANAL_PAUSE 0.250 /* pause after 'Kanalbelegungston' */ +#define TX_LEN_SIGNAL 5.0 /* double tone signal length */ + +/* RX parameters */ +#define RX_MIN_LEVEL 0.1 /* level relative to TONE_LEVEL, below is silence (-20 dB) */ +#define RX_MIN_PREAMBLE 800 /* duration of silence before detecting first digit (in samples) */ +#define RX_DIGIT_FILTER 100.0 /* frequency to allow change of tones ( 100 Hz = 5 ms ) */ +#define RX_TOL_DIGIT_FREQ 0.045 /* maximum frequency error factor allowd to detect a tone (+- 4.5%) */ +#define RX_LEN_DIGIT_TH 80 /* time to wait for digit being stable ( 10 ms ) */ +#define RX_LEN_DIGIT_MIN 400 /* minimum length in seconds allowed for a digit (- 20 ms in samples) */ +#define RX_LEN_DIGIT_MAX 720 /* minimum length in seconds allowed for a digit (+ 20 ms in samples) */ +#define RX_LEN_TONE_MIN 16000 /* minimum length in seconds to detect double tone (2 seconds in samples) */ +#define RX_WAIT_TONE_MAX 48000 /* maximum time to wait for double tone (6 seconds in samples) */ +#define RX_TOL_TONE_FREQ 5.0 /* use +-5 Hz for bandwidth, to make things simpler. (-7.4 dB @ +-5 Hz) */ + +static double digit_freq[DSP_NUM_DIGITS] = { + 1060.0, + 1160.0, + 1270.0, + 1400.0, + 1530.0, + 1670.0, + 1830.0, + 2000.0, + 2200.0, + 2400.0, + 2600.0, /* repeat digit */ +}; +#define DIGIT_FREQ_MIN 1080.0 +#define DIGIT_FREQ_MAX 2600.0 + +#define REPEAT_DIGIT 10 + +/* these are the frequencies of tones to be detected */ +static double tone_freq[DSP_NUM_TONES] = { + 675.0, + 825.0, + 1240.0, + 1860.0, +}; + +#define DSP_NUM_SIGNALS 6 +static struct signals { + enum fuenf_funktion funktion; + int tone1, tone2; +} signals[DSP_NUM_SIGNALS] = { + { FUENF_FUNKTION_FEUER, 0, 2 }, + { FUENF_FUNKTION_PROBE, 0, 3 }, + { FUENF_FUNKTION_WARNUNG, 0, 1 }, + { FUENF_FUNKTION_ABC, 2, 3 }, + { FUENF_FUNKTION_ENTWARNUNG, 1, 3 }, + { FUENF_FUNKTION_KATASTROPHE, 1, 2 }, +}; + +/* Init transceiver instance. */ +int dsp_init_sender(fuenf_t *fuenf, int samplerate, double max_deviation, double signal_deviation) +{ + int i; + int rc; + sample_t *spl; + int len; + + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for transceiver.\n"); + + /* set modulation parameters */ + sender_set_fm(&fuenf->sender, max_deviation, MAX_MODULATION, signal_deviation, MAX_DISPLAY); + + fuenf->sample_duration = 1.0 / (double)samplerate; + + /* init digit demodulator */ + rc = fm_demod_init(&fuenf->rx_digit_demod, 8000, (DIGIT_FREQ_MIN + DIGIT_FREQ_MAX) / 2.0, DIGIT_FREQ_MAX - DIGIT_FREQ_MIN); + if (rc) + goto error; + + /* use fourth order (2 iter) filter, since it is as fast as second order (1 iter) filter */ + iir_lowpass_init(&fuenf->rx_digit_lp, RX_DIGIT_FILTER, 8000, 2); + + /* init signal tone filters */ + for (i = 0; i < DSP_NUM_TONES; i++) + audio_goertzel_init(&fuenf->rx_tone_goertzel[i], tone_freq[i], 8000); + + /* allocate buffer */ + len = (int)(8000.0 * (1.0 / RX_TOL_TONE_FREQ) + 0.5); + spl = calloc(1, len * sizeof(*spl)); + if (!spl) { + PDEBUG(DDSP, DEBUG_ERROR, "No memory!\n"); + goto error; + } + fuenf->rx_tone_filter_spl = spl; + fuenf->rx_tone_filter_size = len; + + /* display values */ + fuenf->dmp_digit_level = display_measurements_add(&fuenf->sender.dispmeas, "Digit Level", "%.0f %%", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0); + for (i = 0; i < DSP_NUM_TONES; i++) { + char name[64]; + sprintf(name, "%.0f Hz Level", tone_freq[i]); + fuenf->dmp_tone_levels[i] = display_measurements_add(&fuenf->sender.dispmeas, name, "%.0f %%", DISPLAY_MEAS_LAST, DISPLAY_MEAS_LEFT, 0.0, 150.0, 100.0); + } + + return 0; + +error: + dsp_cleanup_sender(fuenf); + + return -rc; +} + +/* Cleanup transceiver instance. */ +void dsp_cleanup_sender(fuenf_t *fuenf) +{ + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Cleanup DSP for transceiver.\n"); + + /* free tone buffers */ + if (fuenf->rx_tone_filter_spl) + free(fuenf->rx_tone_filter_spl); +} + +//#define DEBUG + +/* receive digits and decode */ +static void digit_decode(fuenf_t *fuenf, sample_t *samples, int length) +{ + sample_t frequency[length], f, a; + sample_t I[length], Q[length]; + int i, d; + int change, change_count; + + /* tone demodulation */ + fm_demodulate_real(&fuenf->rx_digit_demod, frequency, length, samples, I, Q); + + /* reduce bandwidth of tone detector */ + iir_process(&fuenf->rx_digit_lp, frequency, length); + + /* detect tone */ + for (i = 0; i < length; i++) { + /* get frequency */ + f = frequency[i] + (DIGIT_FREQ_MIN + DIGIT_FREQ_MAX) / 2.0; + + /* get amplitude (a is a sqaure of the amplitude for faster math) */ + a = (I[i] * I[i] + Q[i] * Q[i]) * 2.0 * 2.0 / TONE_LEVEL / TONE_LEVEL; + +#ifdef DEBUG + if (i == 0) printf("%s %.5f ", debug_amplitude(frequency[i] / (DIGIT_FREQ_MAX - DIGIT_FREQ_MIN) * 2.0), f); + if (i == 0) printf("%s %.5f ", debug_amplitude(sqrt(a)), sqrt(a)); +#endif + /* get digit that matches the frequency tolerance */ + for (d = 0; d < DSP_NUM_DIGITS; d++) { + if (f >= digit_freq[d] * (1.0 - RX_TOL_DIGIT_FREQ) && f <= digit_freq[d] * (1.0 + RX_TOL_DIGIT_FREQ)) + break; + } + + /* digit lound enough ? */ + if (a >= RX_MIN_LEVEL * RX_MIN_LEVEL && d < DSP_NUM_DIGITS) { +#ifdef DEBUG + if (i == 0 && d < DSP_NUM_DIGITS) printf("digit=%d (%d == no digit detected)", d, DSP_NUM_DIGITS); +#endif + } else + d = -1; +#ifdef DEBUG + if (i == 0) printf("\n"); +#endif + + /* correct amplitude at cutoff frequency digit '1' and 'repeat'.*/ + if (d == 0 || d == DSP_NUM_DIGITS - 1) + a = a * 2; /* actually 1.414 at cutoff, but a is a square, so we can use 2 */ + + /* count how long this digit sustains, also report if it has changed and when */ + if (d != fuenf->rx_digit_last) { + change = 1; + change_count = fuenf->rx_digit_count; + fuenf->rx_digit_last = d; + fuenf->rx_digit_count = 0; + } else + change = 0; + fuenf->rx_digit_count++; + + /* state machine to detect sequence of 5 tones */ + switch (fuenf->rx_state) { + case RX_STATE_RESET: + /* wait for silence */ + if (d >= 0) + break; + /* check if we have enought silence */ + if (fuenf->rx_digit_count == RX_MIN_PREAMBLE) { + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Detected silence, waiting for digits.\n"); + fuenf->rx_state = RX_STATE_IDLE; + break; + } + break; + case RX_STATE_IDLE: + /* wait for digit */ + if (d < 0) + break; + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "We have some tone, start receiving digits.\n"); + fuenf->rx_callsign_count = 0; + fuenf->rx_callsign[fuenf->rx_callsign_count] = d; + fuenf->rx_state = RX_STATE_DIGIT; + break; + case RX_STATE_DIGIT: + /* wait for change */ + if (!change) { + if (fuenf->rx_digit_count == RX_LEN_DIGIT_TH) { + if (d < 0) { + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Not enough digits received, waiting for next transmission.\n"); + fuenf->rx_function = 0; + fuenf->rx_function_count = 0; + fuenf->rx_state = RX_STATE_RESET; + break; + } + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Detected digit #%d (amplitude = %.0f%%)\n", d + 1, sqrt(a) * 100.0); + display_measurements_update(fuenf->dmp_digit_level, sqrt(a) * 100.0, 0.0); + break; + } + if (fuenf->rx_digit_count == RX_LEN_DIGIT_MAX) { + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Detected digit too long, waiting for next transmission.\n"); + fuenf->rx_state = RX_STATE_RESET; + break; + } + break; + } + /* if digit did not become stable (changed) during threshold */ + if (change_count < RX_LEN_DIGIT_TH) { + /* store detected digit and wait for this one to become stable */ + fuenf->rx_callsign[fuenf->rx_callsign_count] = d; + break; + } + /* if counter (when changed) was too low */ + if (change_count < RX_LEN_DIGIT_MIN) { + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Detected digit too short, waiting for next transmission.\n"); + fuenf->rx_state = RX_STATE_RESET; + break; + } + /* increment digit and store detected digit */ + fuenf->rx_callsign_count++; + fuenf->rx_callsign[fuenf->rx_callsign_count] = d; + /* if 5 tones are received, decode */ + if (fuenf->rx_callsign_count == 5) { + for (i = 0; i < 5; i++) { + if (fuenf->rx_callsign[i] == REPEAT_DIGIT) { + if (i == 0) { + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "First digit is a repeat digit, this is not allowed, waiting for next transmission.\n"); + fuenf->rx_state = RX_STATE_RESET; + break; + } + fuenf->rx_callsign[i] = fuenf->rx_callsign[i - 1]; + } else + if (fuenf->rx_callsign[i] == 9) + fuenf->rx_callsign[i] = '0'; + else + fuenf->rx_callsign[i] = '1' + fuenf->rx_callsign[i]; + } + fuenf->rx_callsign[i] = '\0'; + if (i < 5) + break; + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Complete call sign '%s' received, waiting for signal tone(s).\n", fuenf->rx_callsign); + fuenf_rx_callsign(fuenf, fuenf->rx_callsign); + fuenf->rx_function_count = 0; /* must reset, so we can detect timeout */ + fuenf->rx_state = RX_STATE_WAIT_SIGNAL; + break; + } + break; + default: + /* tones are not decoded here */ + break; + } + } +} + +/* receive tones and decode */ +static void tone_decode(fuenf_t *fuenf, sample_t *samples, int length) +{ + double levels[DSP_NUM_TONES]; + int tone1 = -1, tone2 = -1; + enum fuenf_funktion funktion = 0; + int i; + + /* filter tones */ + audio_goertzel(fuenf->rx_tone_goertzel, samples, length, 0, levels, DSP_NUM_TONES); + for (i = 0; i < DSP_NUM_TONES; i++) + fuenf->rx_tone_levels[i] = levels[i] / TONE_LEVEL; + + /* find two frequencies */ + for (i = 0; i < DSP_NUM_TONES; i++) { + if (fuenf->rx_tone_levels[i] < RX_MIN_LEVEL) + continue; + /* accpet only two ones */ + if (tone1 < 0) + tone1 = i; + else if (tone2 < 0) + tone2 = i; + else { + /* abort, if more than two tones */ + tone1 = -1; + tone2 = -1; + break; + } + } + + /* if exactly two tones */ + if (tone2 >= 0) { + /* select function from signal */ + for (i = 0; i < DSP_NUM_SIGNALS; i++) { + if (tone1 == signals[i].tone1 + && tone2 == signals[i].tone2) { + funktion = signals[i].funktion; + break; + } + } + } + + fuenf->rx_function_count += length; + + /* state machine to detect two tones */ + switch (fuenf->rx_state) { + case RX_STATE_WAIT_SIGNAL: + /* wait for signal */ + if (!funktion) { + if (fuenf->rx_function_count >= RX_WAIT_TONE_MAX) { + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "There is no double tone, waiting for next transmission.\n"); + fuenf->rx_state = RX_STATE_RESET; + break; + } + break; + } + /* store signal */ + fuenf->rx_function = funktion; + fuenf->rx_function_count = 0; + fuenf->rx_state = RX_STATE_SIGNAL; + break; + case RX_STATE_SIGNAL: + /* if signal ceases too early */ + if (funktion != fuenf->rx_function) { + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Signal tones ceased to early, waiting for next transmission.\n"); + fuenf->rx_state = RX_STATE_RESET; + break; + } + if (fuenf->rx_function_count >= RX_LEN_TONE_MIN) { + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Detected tones %.0f+%.0f Hz (amplitude = %.0f%%+%.0f%%)\n", tone_freq[tone1], tone_freq[tone2], fuenf->rx_tone_levels[tone1] * 100.0, fuenf->rx_tone_levels[tone2] * 100.0); + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Signal tones detected, done, waiting for next transmission.\n"); + fuenf_rx_function(fuenf, fuenf->rx_function); + fuenf->rx_state = RX_STATE_RESET; + break; + } + break; + default: + /* digits are not decoded here */ + break; + } +} + +/* Process received audio stream from radio unit. */ +void sender_receive(sender_t *sender, sample_t *samples, int length, double __attribute__((unused)) rf_level_db) +{ + fuenf_t *fuenf = (fuenf_t *) sender; + + if (fuenf->rx) { + sample_t down[length]; + int count, i; + + /* downsample */ + memcpy(down, samples, sizeof(down)); // copy, so audio will not be corrupted at loopback + count = samplerate_downsample(&fuenf->sender.srstate, down, length); + + /* decode digit */ + digit_decode(fuenf, down, count); + + /* decode tone */ + for (i = 0; i < count; i++) { + /* fill buffer and decode when full */ + fuenf->rx_tone_filter_spl[fuenf->rx_tone_filter_pos] = down[i]; + if (++fuenf->rx_tone_filter_pos == fuenf->rx_tone_filter_size) { + tone_decode(fuenf, fuenf->rx_tone_filter_spl, fuenf->rx_tone_filter_size); + fuenf->rx_tone_filter_pos = 0; + } + } + /* display levels */ + for (i = 0; i < DSP_NUM_TONES; i++) + display_measurements_update(fuenf->dmp_tone_levels[i], fuenf->rx_tone_levels[i] * 100.0, 0.0); + } +} + +/* set sequence to send */ +int dsp_setup(fuenf_t *fuenf, const char *rufzeichen, enum fuenf_funktion funktion) +{ + tone_seq_t *seq = fuenf->tx_seq; + int index = 0, tone_index; + int i; + + fuenf->tx_seq_length = 0; + + if (strlen(rufzeichen) != 5) { + PDEBUG_CHAN(DDSP, DEBUG_ERROR, "Given call sign has invalid length.\n"); + return -EINVAL; + } + + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Generating sequence for call sign '%s' and function code '%d'.\n", rufzeichen, funktion); + + /* add preamble */ + seq[index].phasestep1 = 0; + seq[index].phasestep2 = 0; + seq[index].duration = TX_LEN_PREAMBLE; + index++; + + /* add tones */ + tone_index = index; + for (i = 0; rufzeichen[i]; i++) { + if (rufzeichen[i] < '0' || rufzeichen[i] > '9') { + PDEBUG_CHAN(DDSP, DEBUG_ERROR, "Given call sign has invalid digit '%c'.\n", rufzeichen[i]); + return -EINVAL; + } + if (rufzeichen[i] == '0') + seq[index].phasestep1 = 2.0 * M_PI * digit_freq[9] * fuenf->sample_duration; + else + seq[index].phasestep1 = 2.0 * M_PI * digit_freq[rufzeichen[i] - '1'] * fuenf->sample_duration; + /* use repeat digit, if two subsequent digits are the same */ + if (i > 0 && seq[index - 1].phasestep1 == seq[index].phasestep1) { + seq[index].phasestep1 = 2.0 * M_PI * digit_freq[REPEAT_DIGIT] * fuenf->sample_duration; + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, " -> Adding digit '%c' as tone with %.0f Hz.\n", rufzeichen[i], digit_freq[REPEAT_DIGIT]); + } else + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, " -> Adding digit '%c' as tone with %.0f Hz.\n", rufzeichen[i], digit_freq[rufzeichen[i] - '0']); + seq[index].phasestep2 = 0; + seq[index].duration = TX_LEN_DIGIT; + index++; + } + + if (funktion != FUENF_FUNKTION_TURBO) { + /* add pause */ + seq[index].phasestep1 = 0; + seq[index].phasestep2 = 0; + seq[index].duration = TX_LEN_PAUSE; + index++; + + /* add tones (again) */ + for (i = 0; rufzeichen[i]; i++) { + seq[index].phasestep1 = seq[tone_index + i].phasestep1; + seq[index].phasestep2 = 0; + seq[index].duration = TX_LEN_DIGIT; + index++; + } + + /* add (second) pause */ + seq[index].phasestep1 = 0; + seq[index].phasestep2 = 0; + seq[index].duration = TX_LEN_PAUSE; + index++; + } + +#ifndef DEBUG + if (funktion == FUENF_FUNKTION_RUF) { + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, " -> Adding call signal of %.0f Hz.\n", digit_freq[REPEAT_DIGIT]); + for (i = 0; i < TX_NUM_KANAL; i++) { + /* add tone (double volume) */ + seq[index].phasestep1 = 2.0 * M_PI * digit_freq[REPEAT_DIGIT] * fuenf->sample_duration; + seq[index].phasestep2 = 2.0 * M_PI * digit_freq[REPEAT_DIGIT] * fuenf->sample_duration; + seq[index].duration = TX_LEN_KANAL; + index++; + + /* add pause after tone */ + if (i < TX_NUM_KANAL - 1) { + seq[index].phasestep1 = 0; + seq[index].phasestep2 = 0; + seq[index].duration = TX_LEN_KANAL_PAUSE; + index++; + } + } + + /* add postamble */ + seq[index].phasestep1 = 0; + seq[index].phasestep2 = 0; + seq[index].duration = TX_LEN_POSTAMBLE; + index++; + } else + if (funktion != FUENF_FUNKTION_TURBO) { + /* add signal */ + for (i = 0; i < DSP_NUM_SIGNALS; i++) { + if (signals[i].funktion == funktion) + break; + } + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, " -> Adding call signal of %.0f Hz and %.0f Hz.\n", tone_freq[signals[i].tone1], tone_freq[signals[i].tone2]); + seq[index].phasestep1 = 2.0 * M_PI * tone_freq[signals[i].tone1] * fuenf->sample_duration; + seq[index].phasestep2 = 2.0 * M_PI * tone_freq[signals[i].tone2] * fuenf->sample_duration; + seq[index].duration = TX_LEN_SIGNAL; + index++; + } +#endif + + /* check array overflow, if it did not already crashed before */ + if (index > (int)(sizeof(fuenf->tx_seq) / sizeof(fuenf->tx_seq[0]))) { + PDEBUG_CHAN(DDSP, DEBUG_ERROR, "Array size of tx_seq too small, please fix!\n"); + abort(); + } + + fuenf->tx_funktion = funktion; + fuenf->tx_seq_length = index; + fuenf->tx_seq_index = 0; + fuenf->tx_count = 0.0; + + return index; +} + +/* transmit call tone or pause, return 0, if no sequence */ +static int encode(fuenf_t *fuenf, sample_t *samples, int length) +{ + tone_seq_t *seq; + int count = 0; + double value; + + /* no sequence */ + if (!fuenf->tx_seq_length) + return 0; + + seq = &fuenf->tx_seq[fuenf->tx_seq_index]; + + /* generate wave */ + while (count < length && fuenf->tx_count < seq->duration) { + value = 0; + /* reset phase when not sending sine wave */ + if (seq->phasestep1) { + value += sin(fuenf->tx_phase1); + fuenf->tx_phase1 += seq->phasestep1; + } else + fuenf->tx_phase1 = 0.0; + if (seq->phasestep2) { + value += sin(fuenf->tx_phase2); + fuenf->tx_phase2 += seq->phasestep2; + } else + fuenf->tx_phase2 = 0.0; + fuenf->tx_count += fuenf->sample_duration; + *samples++ = value * TONE_LEVEL; + count++; + } + + /* transition to next segment */ + if (fuenf->tx_count >= seq->duration) { + fuenf->tx_count -= seq->duration; + if (++fuenf->tx_seq_index == fuenf->tx_seq_length) { + fuenf->tx_seq_length = 0; + fuenf_tx_done(fuenf); + } + + } + + return count; +} + +/* Provide stream of audio toward radio unit */ +void sender_send(sender_t *sender, sample_t *samples, uint8_t *power, int length) +{ + fuenf_t *fuenf = (fuenf_t *) sender; + sample_t *orig_samples = samples; + int orig_length = length; + int count; + sample_t *spl; + int pos; + int i; + + /* speak through */ + if (fuenf->state == FUENF_STATE_DURCHSAGE && fuenf->callref) { + jitter_load(&fuenf->sender.dejitter, samples, length); + memset(power, 1, length); + } else { + /* send if something has to be sent. else turn transmitter off */ + while ((count = encode(fuenf, samples, length))) { + memset(power, 1, count); + samples += count; + power += count; + length -= count; + } + if (length) { + memset(samples, 0, sizeof(samples) * length); + memset(power, 0, length); + } + } + + /* Also forward audio to network (call process). */ + if (fuenf->callref) { + sample_t copy_samples[orig_length]; +// should we always echo back what we talk through??? +#if 0 + if (fuenf->state == FUENF_STATE_DURCHSAGE) + memset(copy_samples, 0, sizeof(copy_samples)); + else +#endif + memcpy(copy_samples, orig_samples, sizeof(copy_samples)); + count = samplerate_downsample(&fuenf->sender.srstate, copy_samples, orig_length); + spl = fuenf->sender.rxbuf; + pos = fuenf->sender.rxbuf_pos; + for (i = 0; i < count; i++) { + spl[pos++] = copy_samples[i]; + if (pos == 160) { + call_up_audio(fuenf->callref, spl, 160); + pos = 0; + } + } + fuenf->sender.rxbuf_pos = pos; + } else + fuenf->sender.rxbuf_pos = 0; + +} + diff --git a/src/fuenf/dsp.h b/src/fuenf/dsp.h new file mode 100644 index 00000000..7ccb3e84 --- /dev/null +++ b/src/fuenf/dsp.h @@ -0,0 +1,5 @@ + +int dsp_init_sender(fuenf_t *fuenf, int samplerate, double max_deviation, double signal_deviation); +void dsp_cleanup_sender(fuenf_t *fuenf); +int dsp_setup(fuenf_t *fuenf, const char *callsign, enum fuenf_funktion funktion); + diff --git a/src/fuenf/fuenf.c b/src/fuenf/fuenf.c new file mode 100644 index 00000000..4a3eb903 --- /dev/null +++ b/src/fuenf/fuenf.c @@ -0,0 +1,414 @@ +/* 5-Ton-Folge call processing + * + * (C) 2021 by Andreas Eversberg + * All Rights Reserved + * + * 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 3 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, see . + */ + +#define CHAN fuenf->sender.kanal + +#include +#include +#include +#include +#include +#include +#include "../libsample/sample.h" +#include "../libdebug/debug.h" +#include "../libmobile/call.h" +#include "../libmobile/cause.h" +#include "../libosmocc/message.h" +#include "../liboptions/options.h" +#include "fuenf.h" +#include "dsp.h" + +void bos_list_channels(void) +{ + printf("Channels\tBand\n"); + printf("------------------------\n"); + printf("101 - 125\t2 Meter\n"); + printf(" 1 - 92\t2 Meter\n"); + printf("347 - 509\t4 Meter\n"); + printf("-> Give channel number or any frequency in MHz (using a dot, e.g. '169.810').\n"); + printf("\n"); +} + +/* Convert channel to frequency */ +double bos_kanal2freq(const char *kanal) +{ + int k; + + if (strchr(kanal, '.')) + return atof(kanal) * 1e6; + + k = atoi(kanal); + + if (k >= 101 && k <= 125) + return 169.810e6 + 20e3 * (k - 101); + + if (k >= 1 && k <= 92) + return 172.160e6 + 20e3 * (k - 1); + + if (k >= 347 && k <= 509) + return 84.015e6 + 20e3 * (k - 347); + + return 0.0; +} + +/* Convert frequency to channel, if possible */ +const char *bos_freq2kanal(const char *freq) +{ + double f; + char kanal[8]; + + if (!strchr(freq, '.')) + return options_strdup(freq); + + f = atof(freq) * 1e6; + + if (f >= 169.810e6 && f <= 170.290e6 && fmod(f - 169.810e6, 20e3) == 0.0) { + sprintf(kanal, "%.0f", (f - 169.810e6) / 20e3 + 101); + return options_strdup(kanal); + } + + if (f >= 172.160e6 && f <= 173.980e6 && fmod(f - 172.160e6, 20e3) == 0.0) { + sprintf(kanal, "%.0f", (f - 172.160e6) / 20e3 + 1); + return options_strdup(kanal); + } + + if (f >= 84.015e6 && f <= 87.255e6 && fmod(f - 84.015e6, 20e3) == 0.0) { + sprintf(kanal, "%.0f", (f - 84.015e6) / 20e3 + 347); + return options_strdup(kanal); + } + + return options_strdup(freq); +} + +const char *fuenf_state_name[] = { + "IDLE", + "RUF", + "DURCHSAGE", +}; + +const char *fuenf_funktion_name[8] = { + "Ruf", + "Feueralarm", + "Probealarm", + "Warnung der Befoelkerung", + "ABC-Alarm", + "Entwarnung", + "Katastrophenalarm", + "Turbo-Scanner", +}; + +/* check if number is a valid pager ID */ +const char *bos_number_valid(const char *number) +{ + /* assume that the number has valid length(s) and digits */ + + if (number[5] && (number[5] < '0' || number[5] > '6')) + return "Illegal 'Sirenenalarm' digit #6 (Use 1..6 only)"; + return NULL; +} + +int fuenf_init(void) +{ + return 0; +} + +void fuenf_exit(void) +{ +} + +static void fuenf_display_status(void) +{ + sender_t *sender; + fuenf_t *fuenf; + + display_status_start(); + for (sender = sender_head; sender; sender = sender->next) { + fuenf = (fuenf_t *) sender; + display_status_channel(fuenf->sender.kanal, NULL, fuenf_state_name[fuenf->state]); + } + display_status_end(); +} + +void fuenf_new_state(fuenf_t *fuenf, enum fuenf_state new_state) +{ + if (fuenf->state == new_state) + return; + PDEBUG_CHAN(DFUENF, DEBUG_DEBUG, "State change: %s -> %s\n", fuenf_state_name[fuenf->state], fuenf_state_name[new_state]); + fuenf->state = new_state; + fuenf_display_status(); +} + +static int fuenf_scan_or_loopback(fuenf_t *fuenf) +{ + char rufzeichen[16]; + + if (fuenf->scan_from < fuenf->scan_to) { + sprintf(rufzeichen, "%05d", fuenf->scan_from++); + PDEBUG_CHAN(DFUENF, DEBUG_NOTICE, "Transmitting ID '%s'.\n", rufzeichen); + dsp_setup(fuenf, rufzeichen, fuenf->default_funktion); + return 1; + } + + if (fuenf->sender.loopback) { + PDEBUG(DFUENF, DEBUG_INFO, "Sending 5-Ton-Ruf for loopback test.\n"); + dsp_setup(fuenf, "10357", FUENF_FUNKTION_FEUER); + return 1; + } + + return 0; +} + +/* Create transceiver instance and link to a list. */ +int fuenf_create(const char *kanal, double frequency, const char *device, int use_sdr, int samplerate, double rx_gain, double tx_gain, int tx, int rx, double max_deviation, double signal_deviation, enum fuenf_funktion funktion, uint32_t scan_from, uint32_t scan_to, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback) +{ + fuenf_t *fuenf; + int rc; + + fuenf = calloc(1, sizeof(*fuenf)); + if (!fuenf) { + PDEBUG(DFUENF, DEBUG_ERROR, "No memory!\n"); + return -ENOMEM; + } + + PDEBUG(DFUENF, DEBUG_DEBUG, "Creating '5-Ton-Folge' instance for 'Kanal' = %s (sample rate %d).\n", kanal, samplerate); + + /* init general part of transceiver */ + rc = sender_create(&fuenf->sender, kanal, frequency, frequency, device, use_sdr, samplerate, rx_gain, tx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback, PAGING_SIGNAL_NONE); + if (rc < 0) { + PDEBUG(DFUENF, DEBUG_ERROR, "Failed to init transceiver process!\n"); + goto error; + } + + /* init audio processing */ + rc = dsp_init_sender(fuenf, samplerate, max_deviation, signal_deviation); + if (rc < 0) { + PDEBUG(DFUENF, DEBUG_ERROR, "Failed to init audio processing!\n"); + goto error; + } + + fuenf->tx = tx; + fuenf->rx = rx; + fuenf->default_funktion = funktion; + fuenf->scan_from = scan_from; + fuenf->scan_to = scan_to; + + fuenf_display_status(); + + PDEBUG(DFUENF, DEBUG_NOTICE, "Created 'Kanal' %s\n", kanal); + + /* start scanning, if enabled, otherwise send loopback sequence, if enabled */ + fuenf_scan_or_loopback(fuenf); + + return 0; + +error: + fuenf_destroy(&fuenf->sender); + + return rc; +} + +/* Destroy transceiver instance and unlink from list. */ +void fuenf_destroy(sender_t *sender) +{ + fuenf_t *fuenf = (fuenf_t *) sender; + + PDEBUG(DFUENF, DEBUG_DEBUG, "Destroying '5-Ton-Folge' instance for 'Kanal' = %s.\n", sender->kanal); + + dsp_cleanup_sender(fuenf); + sender_destroy(&fuenf->sender); + free(fuenf); +} + +/* call sign was transmitted */ +void fuenf_tx_done(fuenf_t *fuenf) +{ + PDEBUG_CHAN(DFUENF, DEBUG_INFO, "Done sending 5-Ton-Ruf.\n"); + + /* start scanning, if enabled, otherwise send loopback sequence, if enabled */ + if (fuenf_scan_or_loopback(fuenf)) { + return; + } + + /* go talker state */ + if (fuenf->callref && fuenf->tx_funktion == FUENF_FUNKTION_RUF) { + PDEBUG_CHAN(DFUENF, DEBUG_INFO, "Caller may talk now.\n"); + fuenf_new_state(fuenf, FUENF_STATE_DURCHSAGE); + return; + } + + /* go idle */ + fuenf_new_state(fuenf, FUENF_STATE_IDLE); + if (fuenf->callref) { + PDEBUG_CHAN(DFUENF, DEBUG_INFO, "Releasing call toward network.\n"); + call_up_release(fuenf->callref, CAUSE_NORMAL); + } +} + +void fuenf_rx_callsign(fuenf_t *fuenf, const char *callsign) +{ + PDEBUG_CHAN(DFUENF, DEBUG_INFO, "Received 5-Ton-Ruf with call sign '%s'.\n", callsign); +} + +void fuenf_rx_function(fuenf_t *fuenf, enum fuenf_funktion funktion) +{ + PDEBUG_CHAN(DFUENF, DEBUG_INFO, "Received function '%s'.\n", fuenf_funktion_name[funktion]); +} + +void call_down_clock(void) +{ +} + +/* Call control starts call towards transmitter. */ +int call_down_setup(int callref, const char __attribute__((unused)) *caller_id, enum number_type __attribute__((unused)) caller_type, const char *dialing) +{ + char channel = '\0'; + sender_t *sender; + fuenf_t *fuenf; + char rufzeichen[6]; + enum fuenf_funktion funktion; + + /* find transmitter */ + for (sender = sender_head; sender; sender = sender->next) { + /* skip channels that are different than requested */ + if (channel && sender->kanal[0] != channel) + continue; + fuenf = (fuenf_t *) sender; + if (fuenf->state != FUENF_STATE_IDLE) + continue; + /* check if base station cannot transmit */ + if (!fuenf->tx) + continue; + break; + } + if (!sender) { + if (channel) + PDEBUG(DFUENF, DEBUG_NOTICE, "Cannot page, because given station not available, rejecting!\n"); + else + PDEBUG(DFUENF, DEBUG_NOTICE, "Cannot page, no trasmitting station idle, rejecting!\n"); + return -CAUSE_NOCHANNEL; + } + + strncpy(rufzeichen, dialing, 5); + rufzeichen[5] = '\0'; + switch (dialing[5]) { + case '0': + funktion = FUENF_FUNKTION_RUF; + break; + case '1': + funktion = FUENF_FUNKTION_FEUER; + break; + case '2': + funktion = FUENF_FUNKTION_PROBE; + break; + case '3': + funktion = FUENF_FUNKTION_WARNUNG; + break; + case '4': + funktion = FUENF_FUNKTION_ABC; + break; + case '5': + funktion = FUENF_FUNKTION_ENTWARNUNG; + break; + case '6': + funktion = FUENF_FUNKTION_KATASTROPHE; + break; + case '\0': + funktion = fuenf->default_funktion; + break; + default: + return -CAUSE_INVALNUMBER; + } + + PDEBUG_CHAN(DFUENF, DEBUG_INFO, "Sending 5-Ton-Ruf with call sign '%s' and function '%s'.\n", rufzeichen, fuenf_funktion_name[funktion]); + + dsp_setup(fuenf, rufzeichen, funktion); + + fuenf_new_state(fuenf, FUENF_STATE_RUF); + fuenf->callref = callref; + /* must answer to hear paging tones. */ + call_up_answer(fuenf->callref, ""); + + return 0; +} + +void call_down_answer(int __attribute__((unused)) callref) +{ +} + + +static void _release(int __attribute__((unused)) callref, int __attribute__((unused)) cause) +{ + sender_t *sender; + fuenf_t *fuenf; + + PDEBUG(DFUENF, DEBUG_INFO, "Call has been disconnected by network.\n"); + + for (sender = sender_head; sender; sender = sender->next) { + fuenf = (fuenf_t *) sender; + if (fuenf->callref == callref) + break; + } + if (!sender) { + PDEBUG(DBNETZ, DEBUG_NOTICE, "Outgoing release, but no callref!\n"); + /* don't send release, because caller already released */ + return; + } + + /* remove call. go idle, if talking */ + fuenf->callref = 0; + if (fuenf->state == FUENF_STATE_DURCHSAGE) + fuenf_new_state(fuenf, FUENF_STATE_IDLE); +} + +void call_down_disconnect(int callref, int cause) +{ + _release(callref, cause); + + call_up_release(callref, cause); +} + +/* Call control releases call toward mobile station. */ +void call_down_release(int callref, int cause) +{ + _release(callref, cause); +} + +/* Receive audio from call instance. */ +void call_down_audio(int callref, sample_t *samples, int count) +{ + sender_t *sender; + fuenf_t *fuenf; + + for (sender = sender_head; sender; sender = sender->next) { + fuenf = (fuenf_t *) sender; + if (fuenf->callref == callref) + break; + } + if (!sender) + return; + + if (fuenf->state == FUENF_STATE_DURCHSAGE) { + sample_t up[(int)((double)count * fuenf->sender.srstate.factor + 0.5) + 10]; + count = samplerate_upsample(&fuenf->sender.srstate, samples, count, up); + jitter_save(&fuenf->sender.dejitter, up, count); + } +} + +void dump_info(void) {} + diff --git a/src/fuenf/fuenf.h b/src/fuenf/fuenf.h new file mode 100644 index 00000000..cb335c74 --- /dev/null +++ b/src/fuenf/fuenf.h @@ -0,0 +1,100 @@ +#include "../libmobile/sender.h" +#include "../libgoertzel/goertzel.h" +#include "../libfm/fm.h" + +enum fuenf_state { + FUENF_STATE_IDLE = 0, + FUENF_STATE_RUF, + FUENF_STATE_DURCHSAGE, +}; + +extern const char *fuenf_funktion_name[8]; + +enum fuenf_funktion { + FUENF_FUNKTION_RUF = 0, + FUENF_FUNKTION_FEUER, + FUENF_FUNKTION_PROBE, + FUENF_FUNKTION_WARNUNG, + FUENF_FUNKTION_ABC, + FUENF_FUNKTION_ENTWARNUNG, + FUENF_FUNKTION_KATASTROPHE, + FUENF_FUNKTION_TURBO, /* used for turbo scanning, where only pause and 5 tones are sent */ +}; + +enum rx_state { + RX_STATE_RESET = 0, /* wait for silence (after init, double tone or error) */ + RX_STATE_IDLE, /* receive silence, wait for digit */ + RX_STATE_DIGIT, /* wait for end of digit (next digit or silence) */ + RX_STATE_WAIT_SIGNAL, /* wait for double tone (up to 6 sec) */ + RX_STATE_SIGNAL, /* receive double tone and wait for minimum length (2 sec) */ +}; + +/* definition for tone sequence */ +typedef struct tone_seq { + double phasestep1, phasestep2; + double duration; +} tone_seq_t; + +#define DSP_NUM_DIGITS 11 +#define DSP_NUM_TONES 4 + +/* instance of pocsag transmitter/receiver */ +typedef struct fuenf { + sender_t sender; + + /* system info */ + int tx; /* can transmit */ + int rx; /* can receive */ + enum fuenf_funktion default_funktion; /* default function, if not given by caller */ + + /* tx states */ + enum fuenf_state state; /* state (idle, preamble, message) */ + uint32_t scan_from, scan_to; /* if not equal: scnning mode */ + + /* rx states */ + + /* calls */ + int callref; + + /* TX dsp states */ + double sample_duration; /* length between samples in seconds */ + enum fuenf_funktion tx_funktion; + tone_seq_t tx_seq[64]; /* transmit tone sequence */ + int tx_seq_length; /* size of current tone sequence */ + int tx_seq_index; /* current tone that is played */ + double tx_count; /* counts duration of current tone */ + double tx_phase1, tx_phase2; /* current phase of tone */ + + /* display measurements */ + dispmeasparam_t *dmp_digit_level; + dispmeasparam_t *dmp_tone_levels[DSP_NUM_TONES]; + + /* RX dsp states */ + enum rx_state rx_state; /* current state of decoder */ + fm_demod_t rx_digit_demod; /* demodulator for frequency */ + iir_filter_t rx_digit_lp; /* low pass to filter the frequency result */ + int rx_digit_last; /* track if digit changes */ + int rx_digit_count; /* count samples after digit changes */ + goertzel_t rx_tone_goertzel[DSP_NUM_TONES]; /* rx filter */ + sample_t *rx_tone_filter_spl; /* buffer for rx filter */ + int rx_tone_filter_size; /* length of buffer, will affect bandwidth of filter */ + int rx_tone_filter_pos; /* samples in buffer */ + double rx_tone_levels[DSP_NUM_TONES]; /* last detected levels */ + char rx_callsign[6]; /* 5 digits + '\0' */ + int rx_callsign_count; /* number of (complete) digits received */ + enum fuenf_funktion rx_function; /* received signal */ + int rx_function_count; /* counts duration in samples */ +} fuenf_t; + +void bos_list_channels(void); +double bos_kanal2freq(const char *kanal); +const char *bos_freq2kanal(const char *freq); +const char *bos_number_valid(const char *number); +int fuenf_init(void); +void fuenf_exit(void); +int fuenf_create(const char *kanal, double frequency, const char *device, int use_sdr, int samplerate, double rx_gain, double tx_gain, int tx, int rx, double max_deviation, double signal_deviation, enum fuenf_funktion funktion, uint32_t scan_from, uint32_t scan_to, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, const char *read_tx_wave, int loopback); +void fuenf_destroy(sender_t *sender); +void fuenf_tx_done(fuenf_t *fuenf); +void fuenf_rx_callsign(fuenf_t *fuenf, const char *callsign); +void fuenf_rx_function(fuenf_t *fuenf, enum fuenf_funktion funktion); + diff --git a/src/fuenf/image.c b/src/fuenf/image.c new file mode 100644 index 00000000..dcfaebcf --- /dev/null +++ b/src/fuenf/image.c @@ -0,0 +1,24 @@ +#include + +const char *aaimage[] = { + "@w", + " @y______", + " @y__--- ---__", + " @W5-Ton-Folge @y<________________>", + " @w/_ _\\", + " ||", + " _______________________________ ||", + " | _____________________________ | ||", + " | @W[][][][] @w| ||", + " | @W[@y12345 F@w] @W(!) @w| ||", + " | @W(1)(2)(3) (S) @w| ||", + " | @W(4)(5)(6) (#)(#)(#)(#)(#)(#) @w| ||", + " | @W(7)(8)(9) (#)(#)(#)(#)(#)(#) @w| ||", + " | @R(A)@W(0)(L) @B(F)(P)(W)(A)(E)@R(A) @w| ||", + " |_______________________________| ||", + " ||", + " @g. ..\\\\@w||@g//. .@w", + "===============================================================================", + NULL +}; + diff --git a/src/fuenf/main.c b/src/fuenf/main.c new file mode 100644 index 00000000..ab7fa1c0 --- /dev/null +++ b/src/fuenf/main.c @@ -0,0 +1,269 @@ +/* 5-Ton-Folge main + * + * (C) 2021 by Andreas Eversberg + * All Rights Reserved + * + * 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 3 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, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "../libsample/sample.h" +#include "../libdebug/debug.h" +#include "../libmobile/call.h" +#include "../libmobile/main_mobile.h" +#include "../liboptions/options.h" +#include "../anetz/besetztton.h" +#include "fuenf.h" +#include "dsp.h" + +static int tx = 0; /* we transmit */ +static int rx = 0; /* we receive */ +static double max_deviation = 4000; +static double signal_deviation = 2400; +static enum fuenf_funktion funktion = FUENF_FUNKTION_FEUER; +static uint32_t scan_from = 0; +static uint32_t scan_to = 0; + +void print_help(const char *arg0) +{ + main_mobile_print_help(arg0, "-k | -k list"); + /* - - */ + printf(" -T --tx\n"); + printf(" Transmit Eurosignal on given channel, to page a receiver. (default)\n"); + printf(" -R --rx\n"); + printf(" Receive Eurosignal on given channel, so we are the receiver.\n"); + printf(" If none of the options -T nor -R is given, only transmitter is enabled.\n"); + printf(" -D --deviation \n"); + printf(" Choose deviation of FM signal (default %.0f KHz).\n", signal_deviation / 1000.0); + printf(" -F --funktion 0 | ruf | 1 | feuer | 2 | probe | 3 | warnung | 4 | abc\n"); + printf(" | 5 | entwarnung | 6 | katastrophe | 7 | turbo\n"); + printf(" Choose default function when 5 digit only number is dialed.\n"); + printf(" (default %d = %s)\n", funktion, fuenf_funktion_name[funktion]); + printf(" -S --scan \n"); + printf(" Scan through given IDs once (no repetition). This can be useful to find\n"); + printf(" the call sign of a vintage receiver. Note that scanning all call signs\n"); + printf(" from 000000 through 99999 would take about 8.7 days.\n"); + printf(" If 'turbo' function is selected, only a single 5-tone sequence is sent\n"); + printf(" per call sign. A full scan would takte about 26.4 hours then.\n"); + main_mobile_print_station_id(); + main_mobile_print_hotkeys(); +} + +static void add_options(void) +{ + main_mobile_add_options(); + option_add('T', "tx", 0); + option_add('R', "rx", 0); + option_add('D', "deviation", 1); + option_add('F', "funktion", 1); + option_add('S', "scan", 2); +} + +static int handle_options(int short_option, int argi, char **argv) +{ + switch (short_option) { + case 'T': + tx = 1; + break; + case 'R': + rx = 1; + break; + case 'D': + signal_deviation = atof(argv[argi]) * 1000.0; + if (signal_deviation < 1000.0) { + fprintf(stderr, "Given deviation is too low, use higher deviation.\n"); + return -EINVAL; + } + if (signal_deviation > max_deviation) + max_deviation = signal_deviation; + break; + case 'F': + switch (argv[argi][0]) { + case '0': + case 'r': + case 'R': + funktion = FUENF_FUNKTION_RUF; + break; + case '1': + case 'f': + case 'F': + funktion = FUENF_FUNKTION_FEUER; + break; + case '2': + case 'p': + case 'P': + funktion = FUENF_FUNKTION_PROBE; + break; + case '3': + case 'w': + case 'W': + funktion = FUENF_FUNKTION_WARNUNG; + break; + case '4': + case 'a': + case 'A': + funktion = FUENF_FUNKTION_ABC; + break; + case '5': + case 'e': + case 'E': + funktion = FUENF_FUNKTION_ENTWARNUNG; + break; + case '6': + case 'k': + case 'K': + funktion = FUENF_FUNKTION_KATASTROPHE; + break; + case '7': + case 't': + case 'T': + funktion = FUENF_FUNKTION_TURBO; + break; + default: + fprintf(stderr, "Given 'Funktion' is invalid, use '-h' for help.\n"); + return -EINVAL; + } + break; + case 'S': + scan_from = atoi(argv[argi++]); + if (scan_from > 99999) { + fprintf(stderr, "Given call sign to scan from is out of range!\n"); + return -EINVAL; + } + scan_to = atoi(argv[argi++]) + 1; + if (scan_to > 99999) { + fprintf(stderr, "Given call sign to scan to is out of range!\n"); + return -EINVAL; + } + break; + default: + return main_mobile_handle_options(short_option, argi, argv); + } + + return 1; +} + +static const struct number_lengths number_lengths[] = { + { 5, "5-Ton-Folge" }, + { 6, "5-Ton-Folge mit Ruf (0) oder Sirenenalarm (1..6)" }, + { 0, NULL } +}; + +int main(int argc, char *argv[]) +{ + int rc, argi; + const char *station_id = ""; + int i; + const char *k; + double f; + + /* BOS does not use emphasis, so disable it */ + uses_emphasis = 0; + + /* init common tones */ + init_besetzton(); + + /* init mobile interface */ + main_mobile_init("0123456789", number_lengths, NULL, bos_number_valid); + + /* handle options / config file */ + add_options(); + rc = options_config_file(argc, argv, "~/.osmocom/analog/5-ton-folge.conf", handle_options); + if (rc < 0) + return 0; + argi = options_command_line(argc, argv, handle_options); + if (argi <= 0) + return argi; + + if (argi < argc) { + station_id = argv[argi]; + rc = main_mobile_number_ask(station_id, "station ID (RIC)"); + if (rc) + return rc; + } + + if (!num_kanal) { + printf("No channel is specified, Use '-k list' to get a list of all channels.\n\n"); + print_help(argv[0]); + return 0; + } + if (!strcasecmp(kanal[0], "list")) { + bos_list_channels(); + goto fail; + } + if (use_sdr) { + /* set device */ + for (i = 0; i < num_kanal; i++) + dsp_device[i] = "sdr"; + num_device = num_kanal; + } + if (num_kanal == 1 && num_device == 0) + num_device = 1; /* use default */ + if (num_kanal != num_device) { + fprintf(stderr, "You need to specify as many sound devices as you have channels.\n"); + exit(0); + } + + /* TX is default */ + if (!tx && !rx) + tx = 1; + + /* TX & RX if loopback */ + if (loopback) + tx = rx = 1; + + /* inits */ + fm_init(fast_math); + fuenf_init(); + + /* create transceiver instance */ + for (i = 0; i < num_kanal; i++) { + k = bos_freq2kanal(kanal[i]); + f = bos_kanal2freq(k); + if (f == 0.0) { + printf("Invalid channel '%s', Use '-k list' to get a list of all channels.\n\n", k); + goto fail; + } + rc = fuenf_create(k, f, dsp_device[i], use_sdr, dsp_samplerate, rx_gain, tx_gain, tx, rx, max_deviation, signal_deviation, funktion, scan_from, scan_to, write_rx_wave, write_tx_wave, read_rx_wave, read_tx_wave, loopback); + if (rc < 0) { + fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n"); + goto fail; + } + printf("Base station ready, please tune transmitter (or receiver) to %.4f MHz\n", f / 1e6); + } + + main_mobile_loop("5-ton-folge", &quit, NULL, station_id); + +fail: + /* destroy transceiver instance */ + while(sender_head) + fuenf_destroy(sender_head); + + /* exits */ + fm_exit(); + fuenf_exit(); + + options_free(); + + return 0; +} + diff --git a/src/libdebug/debug.c b/src/libdebug/debug.c index 67ba00c5..47dd37a6 100755 --- a/src/libdebug/debug.c +++ b/src/libdebug/debug.c @@ -57,6 +57,7 @@ struct debug_cat { { "jollycom", "\033[1;34m" }, { "eurosignal", "\033[1;34m" }, { "pocsag", "\033[1;34m" }, + { "5-ton-folge", "\033[1;34m" }, { "frame", "\033[0;36m" }, { "call", "\033[0;37m" }, { "cc", "\033[1;32m" }, diff --git a/src/libdebug/debug.h b/src/libdebug/debug.h index ae16857f..f7dd54b3 100644 --- a/src/libdebug/debug.h +++ b/src/libdebug/debug.h @@ -19,38 +19,39 @@ #define DJOLLY 12 #define DEURO 13 #define DPOCSAG 14 -#define DFRAME 15 -#define DCALL 16 -#define DCC 17 -#define DDB 18 -#define DTRANS 19 -#define DDMS 20 -#define DSMS 21 -#define DSDR 22 -#define DUHD 23 -#define DSOAPY 24 -#define DWAVE 25 -#define DRADIO 26 -#define DAM791X 27 -#define DUART 28 -#define DDEVICE 29 -#define DDATENKLO 30 -#define DZEIT 31 -#define DSIM1 32 -#define DSIM2 33 -#define DSIMI 34 -#define DSIM7 35 -#define DMTP2 36 -#define DMTP3 37 -#define DMUP 38 -#define DROUTER 39 -#define DSTDERR 40 -#define DSS5 41 -#define DISDN 42 -#define DMISDN 43 -#define DDSS1 44 -#define DSIP 45 -#define DTEL 46 +#define DFUENF 15 +#define DFRAME 16 +#define DCALL 17 +#define DCC 18 +#define DDB 19 +#define DTRANS 20 +#define DDMS 21 +#define DSMS 22 +#define DSDR 23 +#define DUHD 24 +#define DSOAPY 25 +#define DWAVE 26 +#define DRADIO 27 +#define DAM791X 28 +#define DUART 29 +#define DDEVICE 30 +#define DDATENKLO 31 +#define DZEIT 32 +#define DSIM1 33 +#define DSIM2 34 +#define DSIMI 35 +#define DSIM7 36 +#define DMTP2 37 +#define DMTP3 38 +#define DMUP 39 +#define DROUTER 40 +#define DSTDERR 41 +#define DSS5 42 +#define DISDN 43 +#define DMISDN 44 +#define DDSS1 45 +#define DSIP 46 +#define DTEL 47 void get_win_size(int *w, int *h);