diff --git a/docs/b-netz.html b/docs/b-netz.html index f7997e0..5524f46 100644 --- a/docs/b-netz.html +++ b/docs/b-netz.html @@ -536,7 +536,7 @@ The actual level is not yet relevant. ... bnetz.c:316 info : Entering IDLE state, sending 'Gruppenfreisignal' 2 on channel 1. Base station ready, please tune transmitter to 153.010 MHz and receiver to 148.410 MHz. -To call phone, switch transmitter (using pilot signal) to 153.370 MHz. +To call phone, switch transmitter (using paging signal) to 153.370 MHz. on-hook: ..... (enter 0..9 or d=dial) @@ -555,7 +555,7 @@ Set the selector for the base station ID ("Gruppenfreisignal") to 0. bnetz.c:351 info : Entering IDLE state, sending 'Gruppenfreisignal' 2. Base station for channel 1 ready, please tune transmitter to 153.010 MHz and receiver to 148.410 MHz. -To call phone, switch transmitter (using pilot signal) to 153.370 MHz. +To call phone, switch transmitter (using paging signal) to 153.370 MHz. mncc_sock.c:137 notice : MNCC socket connected. dsp.c:159 info : Detecting continous tone: 2070:Level= 80% Quality=100% bnetz.c:470 info : Received signal 'Kanalbelegung' from mobile station, sending signal 'Wahlabruf'. diff --git a/src/amps/amps.c b/src/amps/amps.c index 8f9b1ad..fd8b03a 100644 --- a/src/amps/amps.c +++ b/src/amps/amps.c @@ -442,7 +442,7 @@ int amps_create(int channel, enum amps_chan_type chan_type, const char *audiodev PDEBUG(DAMPS, DEBUG_DEBUG, "Creating 'AMPS' instance for channel = %d (sample rate %d).\n", channel, samplerate); /* init general part of transceiver */ - rc = sender_create(&s->sender, channel, amps_channel2freq(channel, 0), amps_channel2freq(channel, 1), audiodev, samplerate, rx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PILOT_SIGNAL_NONE); + rc = sender_create(&s->sender, channel, amps_channel2freq(channel, 0), amps_channel2freq(channel, 1), audiodev, samplerate, rx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PAGING_SIGNAL_NONE); if (rc < 0) { PDEBUG(DAMPS, DEBUG_ERROR, "Failed to init transceiver process!\n"); goto error; diff --git a/src/anetz/anetz.c b/src/anetz/anetz.c index 23ec592..539edf7 100644 --- a/src/anetz/anetz.c +++ b/src/anetz/anetz.c @@ -187,7 +187,7 @@ int anetz_create(int kanal, const char *audiodev, int samplerate, double rx_gain PDEBUG(DANETZ, DEBUG_DEBUG, "Creating 'A-Netz' instance for 'Kanal' = %d (sample rate %d).\n", kanal, samplerate); /* init general part of transceiver */ - rc = sender_create(&anetz->sender, kanal, anetz_kanal2freq(kanal, 0), anetz_kanal2freq(kanal, 1), audiodev, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, loss_volume, PILOT_SIGNAL_NONE); + rc = sender_create(&anetz->sender, kanal, anetz_kanal2freq(kanal, 0), anetz_kanal2freq(kanal, 1), audiodev, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, loss_volume, PAGING_SIGNAL_NONE); if (rc < 0) { PDEBUG(DANETZ, DEBUG_ERROR, "Failed to init 'Sender' processing!\n"); goto error; diff --git a/src/bnetz/bnetz.c b/src/bnetz/bnetz.c index 6b8a6d9..fb92ef3 100644 --- a/src/bnetz/bnetz.c +++ b/src/bnetz/bnetz.c @@ -109,23 +109,23 @@ double bnetz_kanal2freq(int kanal, int unterband) return freq * 1e6; } -/* switch pilot signal (tone or file) */ +/* switch paging signal (tone or file) */ static void switch_channel_19(bnetz_t *bnetz, int on) { - /* affects only if pilot signal is used */ - sender_pilot(&bnetz->sender, on); + /* affects only if paging signal is used */ + sender_paging(&bnetz->sender, on); - if (bnetz->pilot_file[0] && bnetz->pilot_is_on != on) { + if (bnetz->paging_file[0] && bnetz->paging_is_on != on) { FILE *fp; - fp = fopen(bnetz->pilot_file, "w"); + fp = fopen(bnetz->paging_file, "w"); if (!fp) { - PDEBUG(DBNETZ, DEBUG_ERROR, "Failed to open file '%s' to switch channel 19!\n", bnetz->pilot_file); + PDEBUG(DBNETZ, DEBUG_ERROR, "Failed to open file '%s' to switch channel 19!\n", bnetz->paging_file); return; } - fprintf(fp, "%s\n", (on) ? bnetz->pilot_on : bnetz->pilot_off); + fprintf(fp, "%s\n", (on) ? bnetz->paging_on : bnetz->paging_off); fclose(fp); - bnetz->pilot_is_on = on; + bnetz->paging_is_on = on; } } @@ -141,11 +141,11 @@ static void bnetz_timeout(struct timer *timer); static void bnetz_go_idle(bnetz_t *bnetz); /* Create transceiver instance and link to a list. */ -int bnetz_create(int kanal, const char *audiodev, int samplerate, double rx_gain, int gfs, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback, double loss_factor, const char *pilot) +int bnetz_create(int kanal, const char *audiodev, int samplerate, double rx_gain, int gfs, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback, double loss_factor, const char *paging) { bnetz_t *bnetz; - enum pilot_signal pilot_signal = PILOT_SIGNAL_NONE; - char pilot_file[256] = "", pilot_on[256] = "", pilot_off[256] = ""; + enum paging_signal paging_signal = PAGING_SIGNAL_NONE; + char paging_file[256] = "", paging_on[256] = "", paging_off[256] = ""; int rc; if (!(kanal >= 1 && kanal <= 39) && !(kanal >= 50 && kanal <= 86)) { @@ -163,34 +163,34 @@ int bnetz_create(int kanal, const char *audiodev, int samplerate, double rx_gain return -EINVAL; } - if (!strcmp(pilot, "notone")) - pilot_signal = PILOT_SIGNAL_NOTONE; + if (!strcmp(paging, "notone")) + paging_signal = PAGING_SIGNAL_NOTONE; else - if (!strcmp(pilot, "tone")) - pilot_signal = PILOT_SIGNAL_TONE; + if (!strcmp(paging, "tone")) + paging_signal = PAGING_SIGNAL_TONE; else - if (!strcmp(pilot, "positive")) - pilot_signal = PILOT_SIGNAL_POSITIVE; + if (!strcmp(paging, "positive")) + paging_signal = PAGING_SIGNAL_POSITIVE; else - if (!strcmp(pilot, "negative")) - pilot_signal = PILOT_SIGNAL_NEGATIVE; + if (!strcmp(paging, "negative")) + paging_signal = PAGING_SIGNAL_NEGATIVE; else { char *p; - strncpy(pilot_file, pilot, sizeof(pilot_file) - 1); - p = strchr(pilot_file, '='); + strncpy(paging_file, paging, sizeof(paging_file) - 1); + p = strchr(paging_file, '='); if (!p) { -error_pilot: - PDEBUG(DBNETZ, DEBUG_ERROR, "Given pilot file (to switch to channel 19) is missing parameters. Use =: format!\n"); +error_paging: + PDEBUG(DBNETZ, DEBUG_ERROR, "Given paging file (to switch to channel 19) is missing parameters. Use =: format!\n"); return -EINVAL; } *p++ = '\0'; - strncpy(pilot_on, p, sizeof(pilot_on) - 1); - p = strchr(pilot_file, ':'); + strncpy(paging_on, p, sizeof(paging_on) - 1); + p = strchr(paging_on, ':'); if (!p) - goto error_pilot; + goto error_paging; *p++ = '\0'; - strncpy(pilot_off, p, sizeof(pilot_off) - 1); + strncpy(paging_off, p, sizeof(paging_off) - 1); } bnetz = calloc(1, sizeof(bnetz_t)); @@ -202,11 +202,12 @@ error_pilot: PDEBUG(DBNETZ, DEBUG_DEBUG, "Creating 'B-Netz' instance for 'Kanal' = %d 'Gruppenfreisignal' = %d (sample rate %d).\n", kanal, gfs, samplerate); /* init general part of transceiver */ - rc = sender_create(&bnetz->sender, kanal, bnetz_kanal2freq(kanal, 0), bnetz_kanal2freq(kanal, 1), audiodev, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, loss_factor, pilot_signal); + rc = sender_create(&bnetz->sender, kanal, bnetz_kanal2freq(kanal, 0), bnetz_kanal2freq(kanal, 1), audiodev, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, loss_factor, paging_signal); if (rc < 0) { PDEBUG(DBNETZ, DEBUG_ERROR, "Failed to init transceiver process!\n"); goto error; } + bnetz->sender.ruffrequenz = bnetz_kanal2freq(19, 0); /* init audio processing */ rc = dsp_init_sender(bnetz); @@ -216,9 +217,9 @@ error_pilot: } bnetz->gfs = gfs; - strncpy(bnetz->pilot_file, pilot_file, sizeof(bnetz->pilot_file) - 1); - strncpy(bnetz->pilot_on, pilot_on, sizeof(bnetz->pilot_on) - 1); - strncpy(bnetz->pilot_off, pilot_off, sizeof(bnetz->pilot_off) - 1); + strncpy(bnetz->paging_file, paging_file, sizeof(bnetz->paging_file) - 1); + strncpy(bnetz->paging_on, paging_on, sizeof(bnetz->paging_on) - 1); + strncpy(bnetz->paging_off, paging_off, sizeof(bnetz->paging_off) - 1); timer_init(&bnetz->timer, bnetz_timeout, bnetz); /* go into idle state */ diff --git a/src/bnetz/bnetz.h b/src/bnetz/bnetz.h index 10f5a6d..dcd3a87 100644 --- a/src/bnetz/bnetz.h +++ b/src/bnetz/bnetz.h @@ -53,10 +53,10 @@ typedef struct bnetz { int gfs; /* 'Gruppenfreisignal' */ /* switch sender to channel 19 */ - char pilot_file[256]; /* if set, write to given file to switch to channel 19 or back */ - char pilot_on[256]; /* what to write to switch to channel 19 */ - char pilot_off[256]; /* what to write to switch back */ - int pilot_is_on; /* set, if we are on channel 19. also used to switch back on exit */ + char paging_file[256]; /* if set, write to given file to switch to channel 19 or back */ + char paging_on[256]; /* what to write to switch to channel 19 */ + char paging_off[256]; /* what to write to switch back */ + int paging_is_on; /* set, if we are on channel 19. also used to switch back on exit */ /* all bnetz states */ enum bnetz_state state; /* main state of sender */ @@ -100,7 +100,7 @@ typedef struct bnetz { double bnetz_kanal2freq(int kanal, int unterband); int bnetz_init(void); -int bnetz_create(int kanal, const char *audiodev, int samplerate, double rx_gain, int gfs, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback, double loss_factor, const char *pilot); +int bnetz_create(int kanal, const char *audiodev, int samplerate, double rx_gain, int gfs, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback, double loss_factor, const char *paging); void bnetz_destroy(sender_t *sender); void bnetz_loss_indication(bnetz_t *bnetz); void bnetz_receive_tone(bnetz_t *bnetz, int bit); diff --git a/src/bnetz/main.c b/src/bnetz/main.c index 7322ca3..409b574 100644 --- a/src/bnetz/main.c +++ b/src/bnetz/main.c @@ -36,8 +36,8 @@ #include "ansage.h" int gfs = 2; -int num_pilot = 0; -const char *pilot[MAX_SENDER] = { "tone" }; +int num_paging = 0; +const char *paging[MAX_SENDER] = { "tone" }; double lossdetect = 0; void print_help(const char *arg0) @@ -53,7 +53,7 @@ void print_help(const char *arg0) printf(" Set to 19 in order to make the phone transmit at 100 mW instead of\n"); printf(" full 15 Watts. If supported, the phone uses the channel with low power\n"); printf(" (Kanal kleiner Leistung).\n"); - printf(" -P --pilot tone | notone | positive | negative | =:\n"); + printf(" -P --paging tone | notone | positive | negative | =:\n"); printf(" Send a tone, give a signal or write to a file when switching to\n"); printf(" channel 19. (paging the phone).\n"); printf(" 'tone', 'positive', 'negative' is sent on second audio channel.\n"); @@ -63,7 +63,7 @@ void print_help(const char *arg0) printf(" 'negative' sends a negative signal for channel 19, else positive.\n"); printf(" Example: /sys/class/gpio/gpio17/value=1:0 writes a '1' to\n"); printf(" /sys/class/gpio/gpio17/value to switching to channel 19 and a '0' to\n"); - printf(" switch back. (default = %s)\n", pilot[0]); + printf(" switch back. (default = %s)\n", paging[0]); printf(" -L --loss \n"); printf(" Detect loss of carrier by detecting steady noise above given volume in\n"); printf(" percent. (disabled by default)\n"); @@ -79,7 +79,7 @@ static int handle_options(int argc, char **argv) static struct option long_options_special[] = { {"gfs", 1, 0, 'G'}, - {"pilot", 1, 0, 'P'}, + {"paging", 1, 0, 'P'}, {"loss", 1, 0, 'L'}, {0, 0, 0, 0}, }; @@ -109,7 +109,7 @@ static int handle_options(int argc, char **argv) skip_args += 2; break; case 'P': - OPT_ARRAY(num_pilot, pilot, strdup(optarg)) + OPT_ARRAY(num_paging, paging, strdup(optarg)) skip_args += 2; break; case 'L': @@ -159,10 +159,10 @@ int main(int argc, char *argv[]) fprintf(stderr, "You need to specify as many sound devices as you have channels.\n"); exit(0); } - if (num_kanal == 1 && num_pilot == 0) - num_pilot = 1; /* use defualt */ - if (num_kanal != num_pilot) { - fprintf(stderr, "You need to specify as many pilot tone settings as you have channels.\n"); + if (num_kanal == 1 && num_paging == 0) + num_paging = 1; /* use defualt */ + if (num_kanal != num_paging) { + fprintf(stderr, "You need to specify as many paging tone settings as you have channels.\n"); exit(0); } @@ -187,13 +187,13 @@ int main(int argc, char *argv[]) /* create transceiver instance */ for (i = 0; i < num_kanal; i++) { - rc = bnetz_create(kanal[i], audiodev[i], samplerate, rx_gain, gfs, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, (double)lossdetect / 100.0, pilot[i]); + rc = bnetz_create(kanal[i], audiodev[i], samplerate, rx_gain, gfs, do_pre_emphasis, do_de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, (double)lossdetect / 100.0, paging[i]); if (rc < 0) { fprintf(stderr, "Failed to create \"Sender\" instance. Quitting!\n"); goto fail; } printf("Base station for channel %d ready, please tune transmitter to %.3f MHz and receiver " "to %.3f MHz.\n", kanal[i], bnetz_kanal2freq(kanal[i], 0) / 1e6, bnetz_kanal2freq(kanal[i], 1) / 1e6); - printf("To call phone, switch transmitter (using pilot signal) to %.3f MHz.\n", bnetz_kanal2freq(19, 0) / 1e6); + printf("To call phone, switch transmitter (using paging signal) to %.3f MHz.\n", bnetz_kanal2freq(19, 0) / 1e6); } main_common(&quit, latency, interval, NULL); diff --git a/src/cnetz/cnetz.c b/src/cnetz/cnetz.c index f0a4ec5..71795da 100644 --- a/src/cnetz/cnetz.c +++ b/src/cnetz/cnetz.c @@ -274,7 +274,7 @@ int cnetz_create(int kanal, enum cnetz_chan_type chan_type, const char *audiodev /* init general part of transceiver */ /* do not enable emphasis, since it is done by cnetz code, not by common sender code */ - rc = sender_create(&cnetz->sender, kanal, cnetz_kanal2freq(kanal, 0), cnetz_kanal2freq(kanal, 1), audiodev, samplerate, rx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PILOT_SIGNAL_NONE); + rc = sender_create(&cnetz->sender, kanal, cnetz_kanal2freq(kanal, 0), cnetz_kanal2freq(kanal, 1), audiodev, samplerate, rx_gain, 0, 0, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PAGING_SIGNAL_NONE); if (rc < 0) { PDEBUG(DCNETZ, DEBUG_ERROR, "Failed to init transceiver process!\n"); goto error; diff --git a/src/common/call.c b/src/common/call.c index ab57390..50370ec 100644 --- a/src/common/call.c +++ b/src/common/call.c @@ -473,7 +473,7 @@ int call_init(const char *station_id, const char *audiodev, int samplerate, int return 0; /* open sound device for call control */ - call.sound = sound_open(audiodev, NULL, NULL, 1, samplerate, 3700.0, 0.0); + call.sound = sound_open(audiodev, NULL, NULL, 1, 0.0, samplerate, 3700.0, 0.0); if (!call.sound) { PDEBUG(DSENDER, DEBUG_ERROR, "No sound device!\n"); @@ -671,7 +671,7 @@ void process_call(int c) jitter_load(&call.dejitter, up, count); } spl_list[0] = up; - rc = sound_write(call.sound, spl_list, count, 1); + rc = sound_write(call.sound, spl_list, count, NULL, NULL, 1); if (rc < 0) { PDEBUG(DSENDER, DEBUG_ERROR, "Failed to write TX data to sound device (rc = %d)\n", rc); if (rc == -EPIPE) diff --git a/src/common/sdr.c b/src/common/sdr.c index c2b38dc..527c291 100644 --- a/src/common/sdr.c +++ b/src/common/sdr.c @@ -17,12 +17,13 @@ * along with this program. If not, see . */ +#include #include #include #include #include #include "filter.h" -#include "sdr.h" +#include "sender.h" #ifdef HAVE_UHD #include "uhd.h" #endif @@ -42,7 +43,9 @@ typedef struct sdr_chan { } sdr_chan_t; typedef struct sdr { - sdr_chan_t *chan; + sdr_chan_t *chan; /* settings for all channels */ + int paging_channel; /* if set, points to paging channel */ + sdr_chan_t paging_chan; /* settings for extra paging channel */ double spl_deviation; /* how to convert a sample step into deviation (Hz) */ int channels; /* number of frequencies */ double samplerate; /* IQ rate */ @@ -73,10 +76,10 @@ int sdr_init(const char *device_args, double rx_gain, double tx_gain) return 0; } -void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_frequency, double *rx_frequency, int channels, int samplerate, double bandwidth, double sample_deviation) +void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double bandwidth, double sample_deviation) { sdr_t *sdr; - double center_frequency; + double tx_center_frequency, rx_center_frequency; int rc; int c; @@ -95,8 +98,14 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq sdr->spl_deviation = sample_deviation; sdr->amplitude = 0.4 / (double)channels; // FIXME: actual amplitude 0.1? + /* special case where we use a paging frequency */ + if (paging_frequency) { + /* add extra paging channel */ + sdr->paging_channel = channels; + } + /* create list of channel states */ - sdr->chan = calloc(sizeof(*sdr->chan), channels); + sdr->chan = calloc(sizeof(*sdr->chan), channels + (sdr->paging_channel != 0)); if (!sdr->chan) { PDEBUG(DSDR, DEBUG_ERROR, "NO MEM!\n"); goto error; @@ -105,43 +114,74 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq PDEBUG(DSDR, DEBUG_INFO, "Frequency #%d: TX = %.6f MHz, RX = %.6f MHz\n", c, tx_frequency[c] / 1e6, rx_frequency[c] / 1e6); sdr->chan[c].tx_frequency = tx_frequency[c]; sdr->chan[c].rx_frequency = rx_frequency[c]; -#warning check rx frequency is in range filter_lowpass_init(&sdr->chan[c].rx_lp[0], bandwidth, samplerate); filter_lowpass_init(&sdr->chan[c].rx_lp[1], bandwidth, samplerate); } + if (sdr->paging_channel) { + PDEBUG(DSDR, DEBUG_INFO, "Paging Frequency: TX = %.6f MHz\n", paging_frequency / 1e6); + sdr->chan[sdr->paging_channel].tx_frequency = paging_frequency; + } /* calculate required bandwidth (IQ rate) */ - if (channels == 1) { - PDEBUG(DSDR, DEBUG_INFO, "Single frequency, so we use sample rate as IQ bandwidth: %.6f MHz\n", sdr->samplerate / 1e6); - center_frequency = sdr->chan[0].tx_frequency; - } else { - double low_frequency = sdr->chan[0].tx_frequency, high_frequency = sdr->chan[0].tx_frequency, range; - for (c = 1; c < channels; c++) { - if (sdr->chan[c].tx_frequency < low_frequency) - low_frequency = sdr->chan[c].tx_frequency; - if (sdr->chan[c].tx_frequency > high_frequency) - high_frequency = sdr->chan[c].tx_frequency; - } - range = high_frequency - low_frequency; - PDEBUG(DSDR, DEBUG_INFO, "Range between frequencies: %.6f MHz\n", range / 1e6); - if (range * 2 > sdr->samplerate) { - // why that? actually i don't know. i just want to be safe.... - PDEBUG(DSDR, DEBUG_NOTICE, "The sample rate must be at least twice the range between frequencies. Please increment samplerate!\n"); - goto error; - } - center_frequency = (high_frequency + low_frequency) / 2.0; + double tx_low_frequency = sdr->chan[0].tx_frequency, tx_high_frequency = sdr->chan[0].tx_frequency; + double rx_low_frequency = sdr->chan[0].rx_frequency, rx_high_frequency = sdr->chan[0].rx_frequency; + double range; + for (c = 1; c < channels; c++) { + if (sdr->chan[c].tx_frequency < tx_low_frequency) + tx_low_frequency = sdr->chan[c].tx_frequency; + if (sdr->chan[c].tx_frequency > tx_high_frequency) + tx_high_frequency = sdr->chan[c].tx_frequency; + if (sdr->chan[c].rx_frequency < rx_low_frequency) + rx_low_frequency = sdr->chan[c].rx_frequency; + if (sdr->chan[c].rx_frequency > rx_high_frequency) + rx_high_frequency = sdr->chan[c].rx_frequency; } - PDEBUG(DSDR, DEBUG_INFO, "Using center frequency: %.6f MHz\n", center_frequency / 1e6); + if (sdr->paging_channel) { + if (sdr->chan[sdr->paging_channel].tx_frequency < tx_low_frequency) + tx_low_frequency = sdr->chan[sdr->paging_channel].tx_frequency; + if (sdr->chan[sdr->paging_channel].tx_frequency > tx_high_frequency) + tx_high_frequency = sdr->chan[sdr->paging_channel].tx_frequency; + } + /* range of TX */ + range = tx_high_frequency - tx_low_frequency; + if (range) + PDEBUG(DSDR, DEBUG_INFO, "Range between all TX Frequencies: %.6f MHz\n", range / 1e6); + if (range * 2 > sdr->samplerate) { + // why that? actually i don't know. i just want to be safe.... + PDEBUG(DSDR, DEBUG_NOTICE, "The sample rate must be at least twice the range between frequencies.\n"); + PDEBUG(DSDR, DEBUG_NOTICE, "The given rate is %.6f MHz, but required rate must be >= %.6f MHz\n", sdr->samplerate / 1e6, range * 2.0 / 1e6); + PDEBUG(DSDR, DEBUG_NOTICE, "Please increase samplerate!\n"); + goto error; + } + tx_center_frequency = (tx_high_frequency + tx_low_frequency) / 2.0; + PDEBUG(DSDR, DEBUG_INFO, "Using TX center frequency: %.6f MHz\n", tx_center_frequency / 1e6); + /* range of RX */ + range = rx_high_frequency - rx_low_frequency; + if (range) + PDEBUG(DSDR, DEBUG_INFO, "Range between all RX Frequencies: %.6f MHz\n", range / 1e6); + if (range * 2.0 > sdr->samplerate) { + // why that? actually i don't know. i just want to be safe.... + PDEBUG(DSDR, DEBUG_NOTICE, "The sample rate must be at least twice the range between frequencies. Please increment samplerate!\n"); + goto error; + } + rx_center_frequency = (rx_high_frequency + rx_low_frequency) / 2.0; + PDEBUG(DSDR, DEBUG_INFO, "Using RX center frequency: %.6f MHz\n", rx_center_frequency / 1e6); + /* set offsets to center frequency */ for (c = 0; c < channels; c++) { - sdr->chan[c].offset = sdr->chan[c].tx_frequency - center_frequency; - sdr->chan[c].rx_rot = 2 * M_PI * -sdr->chan[c].offset / sdr->samplerate; - PDEBUG(DSDR, DEBUG_INFO, "Frequency #%d offset: %.6f MHz\n", c, sdr->chan[c].offset / 1e6); + double rx_offset; + sdr->chan[c].offset = sdr->chan[c].tx_frequency - tx_center_frequency; + rx_offset = sdr->chan[c].rx_frequency - rx_center_frequency; + sdr->chan[c].rx_rot = 2 * M_PI * -rx_offset / sdr->samplerate; + PDEBUG(DSDR, DEBUG_INFO, "Frequency #%d: TX offset: %.6f MHz, RX offset: %.6f MHz\n", c, sdr->chan[c].offset / 1e6, rx_offset / 1e6); + } + if (sdr->paging_channel) { + sdr->chan[sdr->paging_channel].offset = sdr->chan[sdr->paging_channel].tx_frequency - tx_center_frequency; + PDEBUG(DSDR, DEBUG_INFO, "Paging Frequency: TX offset: %.6f MHz\n", sdr->chan[sdr->paging_channel].offset / 1e6); } PDEBUG(DSDR, DEBUG_INFO, "Using gain: TX %.1f dB, RX %.1f dB\n", sdr_tx_gain, sdr_rx_gain); #ifdef HAVE_UHD -#warning hack - rc = uhd_open(sdr_device_args, center_frequency, center_frequency - sdr->chan[0].tx_frequency + sdr->chan[0].rx_frequency, sdr->samplerate, sdr_rx_gain, sdr_tx_gain); + rc = uhd_open(sdr_device_args, tx_center_frequency, rx_center_frequency, sdr->samplerate, sdr_rx_gain, sdr_tx_gain); if (rc) goto error; #endif @@ -168,12 +208,12 @@ void sdr_close(void *inst) } } -int sdr_write(void *inst, int16_t **samples, int num, int channels) +int sdr_write(void *inst, int16_t **samples, int num, enum paging_signal __attribute__((unused)) *paging_signal, int *on, int channels) { sdr_t *sdr = (sdr_t *)inst; float buff[num * 2]; int c, s, ss; - double rate, phase, amplitude, dev; + double rate, offset, phase, amplitude, dev; int sent; if (channels != sdr->channels) { @@ -186,11 +226,16 @@ int sdr_write(void *inst, int16_t **samples, int num, int channels) amplitude = sdr->amplitude; memset(buff, 0, sizeof(buff)); for (c = 0; c < channels; c++) { - /* modulate */ phase = sdr->chan[c].tx_phase; + /* switch offset to paging channel, if requested */ + if (on[c] && sdr->paging_channel) + offset = sdr->chan[sdr->paging_channel].offset; + else + offset = sdr->chan[c].offset; + /* modulate */ for (s = 0, ss = 0; s < num; s++) { /* deviation is defined by the sample value and the offset */ - dev = sdr->chan[c].offset + (double)samples[c][s] * sdr->spl_deviation; + dev = offset + (double)samples[c][s] * sdr->spl_deviation; #ifdef FAST_SINE phase += 256.0 * dev / rate; if (phase < 0.0) @@ -249,7 +294,6 @@ int sdr_read(void *inst, int16_t **samples, int num, int channels) Q[s] = i * sin(phase) + q * cos(phase); } sdr->chan[c].rx_phase = phase; -#warning eine interation von 2 führt zu müll (2. kanal gespiegeltes audio), muss man genauer mal analysieren filter_lowpass_process(&sdr->chan[c].rx_lp[0], I, count, 1); filter_lowpass_process(&sdr->chan[c].rx_lp[1], Q, count, 1); last_phase = sdr->chan[c].rx_last_phase; diff --git a/src/common/sdr.h b/src/common/sdr.h index da3ccb0..ecbcbe4 100644 --- a/src/common/sdr.h +++ b/src/common/sdr.h @@ -1,8 +1,8 @@ int sdr_init(const char *device_args, double rx_gain, double tx_gain); -void *sdr_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int channels, int samplerate, double bandwidth, double sample_deviation); +void *sdr_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double bandwidth, double sample_deviation); void sdr_close(void *inst); -int sdr_write(void *inst, int16_t **samples, int num, int channels); +int sdr_write(void *inst, int16_t **samples, int num, enum paging_signal *paging_signal, int *on, int channels); int sdr_read(void *inst, int16_t **samples, int num, int channels); int sdr_get_inbuffer(void *inst); diff --git a/src/common/sender.c b/src/common/sender.c index a579388..f610dbc 100644 --- a/src/common/sender.c +++ b/src/common/sender.c @@ -32,7 +32,7 @@ static sender_t **sender_tailp = &sender_head; int cant_recover = 0; /* Init transceiver instance and link to list of transceivers. */ -int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empfangsfrequenz, const char *audiodev, int samplerate, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback, double loss_volume, enum pilot_signal pilot_signal) +int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empfangsfrequenz, const char *audiodev, int samplerate, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback, double loss_volume, enum paging_signal paging_signal) { sender_t *master, *slave; int rc = 0; @@ -49,12 +49,7 @@ int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empf sender->de_emphasis = de_emphasis; sender->loopback = loopback; sender->loss_volume = loss_volume; -#ifdef HAVE_SDR - if (!strcmp(audiodev, "sdr")) - pilot_signal = PILOT_SIGNAL_NONE; -#endif - sender->pilot_signal = pilot_signal; - sender->pilotton_phaseshift = 1.0 / ((double)samplerate / 1000.0); + sender->paging_signal = paging_signal; PDEBUG_CHAN(DSENDER, DEBUG_DEBUG, "Creating 'Sender' instance\n"); @@ -73,13 +68,13 @@ int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empf break; } if (master) { - if (master->pilot_signal != PILOT_SIGNAL_NONE) { - PDEBUG(DSENDER, DEBUG_ERROR, "Cannot share audio device with channel %d, because second channel is used for pilot signal!\n", master->kanal); + if (master->paging_signal != PAGING_SIGNAL_NONE && !!strcmp(master->audiodev, "sdr")) { + PDEBUG(DSENDER, DEBUG_ERROR, "Cannot share audio device with channel %d, because its second audio channel is used for paging signal! Use different audio device.\n", master->kanal); rc = -EBUSY; goto error; } - if (pilot_signal != PILOT_SIGNAL_NONE) { - PDEBUG(DSENDER, DEBUG_ERROR, "Cannot share audio device with channel %d, because we need a stereo channel for pilot signal!\n", master->kanal); + if (paging_signal != PAGING_SIGNAL_NONE && !!strcmp(audiodev, "sdr")) { + PDEBUG(DSENDER, DEBUG_ERROR, "Cannot share audio device with channel %d, because we need a second audio channel for paging signal! Use different audio device.\n", master->kanal); rc = -EBUSY; goto error; } @@ -95,10 +90,6 @@ int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empf /* link audio device */ #ifdef HAVE_SDR if (!strcmp(audiodev, "sdr")) { - if (pilot_signal != PILOT_SIGNAL_NONE) { - PDEBUG(DSENDER, DEBUG_ERROR, "No pilot signal allowed with SDR, please fix!\n"); - abort(); - } sender->audio_open = sdr_open; sender->audio_close = sdr_close; sender->audio_read = sdr_read; @@ -169,6 +160,7 @@ int sender_open_audio(void) { sender_t *master, *inst; int channels; + double paging_frequency = 0.0; int i; for (master = sender_head; master; master = master->next) { @@ -188,10 +180,12 @@ int sender_open_audio(void) rx_f[i] = inst->sendefrequenz; else rx_f[i] = inst->empfangsfrequenz; + if (inst->ruffrequenz) + paging_frequency = inst->ruffrequenz; } /* open device */ - master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, master->samplerate, master->bandwidth, master->sample_deviation); + master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, paging_frequency, master->samplerate, master->bandwidth, master->sample_deviation); if (!master->audio) { PDEBUG(DSENDER, DEBUG_ERROR, "No audio device!\n"); return -EIO; @@ -226,27 +220,6 @@ void sender_destroy(sender_t *sender) jitter_destroy(&sender->dejitter); } -static void gen_pilotton(sender_t *sender, int16_t *samples, int length) -{ - double phaseshift, phase; - int i; - - phaseshift = sender->pilotton_phaseshift; - phase = sender->pilotton_phase; - - for (i = 0; i < length; i++) { - if (phase < 0.5) - *samples++ = 30000; - else - *samples++ = -30000; - phase += phaseshift; - if (phase >= 1.0) - phase -= 1.0; - } - - sender->pilotton_phase = phase; -} - static void gain_samples(int16_t *samples, int length, double gain) { int i; @@ -271,16 +244,12 @@ void process_sender_audio(sender_t *sender, int *quit, int latspl) /* count instances for audio channel */ for (num_chan = 0, inst = sender; inst; num_chan++, inst = inst->slave); - if (sender->pilot_signal != PILOT_SIGNAL_NONE) { - if (num_chan != 1) { - PDEBUG(DSENDER, DEBUG_ERROR, "Software error, please fix!\n"); - abort(); - } - num_chan = 2; - } int16_t buff[num_chan][latspl], *samples[num_chan]; - for (i = 0; i < num_chan; i++) + enum paging_signal paging_signal[num_chan]; + int on[num_chan]; + for (i = 0; i < num_chan; i++) { samples[i] = buff[i]; + } count = sender->audio_get_inbuffer(sender->audio); if (count < 0) { @@ -321,41 +290,12 @@ cant_recover: /* do pre emphasis towards radio, not wave_write */ if (inst->pre_emphasis) pre_emphasis(&inst->estate, samples[i], count); - } - switch (sender->pilot_signal) { - case PILOT_SIGNAL_TONE: - /* tone if pilot signal is on */ - if (sender->pilot_on) - gen_pilotton(sender, samples[1], count); - else - memset(samples[1], 0, count << 1); - break; - case PILOT_SIGNAL_NOTONE: - /* tone if pilot signal is off */ - if (!sender->pilot_on) - gen_pilotton(sender, samples[1], count); - else - memset(samples[1], 0, count << 1); - break; - case PILOT_SIGNAL_POSITIVE: - /* positive signal if pilot signal is on */ - if (sender->pilot_on) - memset(samples[1], 127, count << 1); - else - memset(samples[1], 128, count << 1); - break; - case PILOT_SIGNAL_NEGATIVE: - /* negative signal if pilot signal is on */ - if (sender->pilot_on) - memset(samples[1], 128, count << 1); - else - memset(samples[1], 127, count << 1); - break; - case PILOT_SIGNAL_NONE: - break; + /* set paging signal */ + paging_signal[i] = sender->paging_signal; + on[i] = sender->paging_on; } - rc = sender->audio_write(sender->audio, samples, count, num_chan); + rc = sender->audio_write(sender->audio, samples, count, paging_signal, on, num_chan); if (rc < 0) { PDEBUG(DSENDER, DEBUG_ERROR, "Failed to write TX data to audio device (rc = %d)\n", rc); if (rc == -EPIPE) { @@ -406,8 +346,8 @@ transmit_later: } } -void sender_pilot(sender_t *sender, int on) +void sender_paging(sender_t *sender, int on) { - sender->pilot_on = on; + sender->paging_on = on; } diff --git a/src/common/sender.h b/src/common/sender.h index c655ca6..5dbdf52 100644 --- a/src/common/sender.h +++ b/src/common/sender.h @@ -11,13 +11,13 @@ #define MAX_SENDER 16 -/* how to send a 'pilot' signal (trigger transmitter) */ -enum pilot_signal { - PILOT_SIGNAL_NONE = 0, - PILOT_SIGNAL_TONE, - PILOT_SIGNAL_NOTONE, - PILOT_SIGNAL_POSITIVE, - PILOT_SIGNAL_NEGATIVE, +/* how to send a 'paging' signal (trigger transmitter) */ +enum paging_signal { + PAGING_SIGNAL_NONE = 0, + PAGING_SIGNAL_TONE, + PAGING_SIGNAL_NOTONE, + PAGING_SIGNAL_POSITIVE, + PAGING_SIGNAL_NEGATIVE, }; /* common structure of each transmitter */ @@ -30,15 +30,16 @@ typedef struct sender { int kanal; /* channel number */ double sendefrequenz; /* transmitter frequency */ double empfangsfrequenz; /* receiver frequency */ + double ruffrequenz; /* special paging frequency used for B-Netz */ double bandwidth; /* max NF frequency to be transmitted unaffected by filtering */ double sample_deviation; /* frequency deviation of one sample step (after pre-emphasis) */ /* audio */ void *audio; char audiodev[64]; /* audio device name (alsa or sdr) */ - void *(*audio_open)(const char *, double *, double *, int, int, double, double); + void *(*audio_open)(const char *, double *, double *, int, double, int, double, double); void (*audio_close)(void *); - int (*audio_write)(void *, int16_t **, int, int); + int (*audio_write)(void *, int16_t **, int, enum paging_signal *, int *, int); int (*audio_read)(void *, int16_t **, int, int); int (*audio_get_inbuffer)(void *); int samplerate; @@ -67,11 +68,9 @@ typedef struct sender { double loss_volume; loss_t loss; - /* pilot tone */ - enum pilot_signal pilot_signal; /* if pilot signal is used and how it is performed */ - int pilot_on; /* 1 or 0 for on or off */ - double pilotton_phaseshift; /* phase to shift every sample */ - double pilotton_phase; /* current phase */ + /* paging tone */ + enum paging_signal paging_signal; /* if paging signal is used and how it is performed */ + int paging_on; /* 1 or 0 for on or off */ /* display wave */ dispwav_t dispwav; /* display wave form */ @@ -81,11 +80,11 @@ typedef struct sender { extern sender_t *sender_head; extern int cant_recover; -int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empfangsfrequenz, const char *audiodev, int samplerate, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback, double loss_volume, enum pilot_signal pilot_signal); +int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empfangsfrequenz, const char *audiodev, int samplerate, double rx_gain, int pre_emphasis, int de_emphasis, const char *write_rx_wave, const char *write_tx_wave, const char *read_rx_wave, int loopback, double loss_volume, enum paging_signal paging_signal); void sender_destroy(sender_t *sender); int sender_open_audio(void); void process_sender_audio(sender_t *sender, int *quit, int latspl); void sender_send(sender_t *sender, int16_t *samples, int count); void sender_receive(sender_t *sender, int16_t *samples, int count); -void sender_pilot(sender_t *sender, int on); +void sender_paging(sender_t *sender, int on); diff --git a/src/common/sound.h b/src/common/sound.h index 313a559..a352f06 100644 --- a/src/common/sound.h +++ b/src/common/sound.h @@ -1,7 +1,9 @@ -void *sound_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int channels, int samplerate, double bandwidth, double sample_deviation); +enum paging_signal; + +void *sound_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double bandwidth, double sample_deviation); void sound_close(void *inst); -int sound_write(void *inst, int16_t **samples, int num, int channels); +int sound_write(void *inst, int16_t **samples, int num, enum paging_signal *paging_signal, int *on, int channels); int sound_read(void *inst, int16_t **samples, int num, int channels); int sound_get_inbuffer(void *inst); diff --git a/src/common/sound_alsa.c b/src/common/sound_alsa.c index c8d0668..4eef893 100644 --- a/src/common/sound_alsa.c +++ b/src/common/sound_alsa.c @@ -21,11 +21,13 @@ #include #include #include "debug.h" -#include "sound.h" +#include "sender.h" typedef struct sound { snd_pcm_t *phandle, *chandle; int pchannels, cchannels; + double paging_phaseshift; /* phase to shift every sample */ + double paging_phase; /* current phase */ } sound_t; static int set_hw_params(snd_pcm_t *handle, int samplerate, int *channels) @@ -128,7 +130,7 @@ static int sound_prepare(sound_t *sound) return 0; } -void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int channels, int samplerate, double __attribute__((unused)) bandwidth, double __attribute__((unused)) sample_deviation) +void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_frequency, double __attribute__((unused)) *rx_frequency, int channels, double __attribute__((unused)) paging_frequency, int samplerate, double __attribute__((unused)) bandwidth, double __attribute__((unused)) sample_deviation) { sound_t *sound; int rc; @@ -144,6 +146,8 @@ void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_freque return NULL; } + sound->paging_phaseshift = 1.0 / ((double)samplerate / 1000.0); + rc = snd_pcm_open(&sound->phandle, audiodev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if (rc < 0) { PDEBUG(DSOUND, DEBUG_ERROR, "Failed to open '%s' for playback! (%s)\n", audiodev, snd_strerror(rc)); @@ -200,7 +204,51 @@ void sound_close(void *inst) free(sound); } -int sound_write(void *inst, int16_t **samples, int num, int channels) +static void gen_paging_tone(sound_t *sound, int16_t *samples, int length, enum paging_signal paging_signal, int on) +{ + double phaseshift, phase; + int i; + + switch (paging_signal) { + case PAGING_SIGNAL_NOTONE: + /* no tone if paging signal is on */ + on = !on; + // fall through + case PAGING_SIGNAL_TONE: + /* tone if paging signal is on */ + if (on) { + phaseshift = sound->paging_phaseshift; + phase = sound->paging_phase; + for (i = 0; i < length; i++) { + if (phase < 0.5) + *samples++ = 30000; + else + *samples++ = -30000; + phase += phaseshift; + if (phase >= 1.0) + phase -= 1.0; + } + sound->paging_phase = phase; + } else + memset(samples, 0, length << 1); + break; + case PAGING_SIGNAL_NEGATIVE: + /* negative signal if paging signal is on */ + on = !on; + // fall through + case PAGING_SIGNAL_POSITIVE: + /* positive signal if paging signal is on */ + if (on) + memset(samples, 127, length << 1); + else + memset(samples, 128, length << 1); + break; + case PAGING_SIGNAL_NONE: + break; + } +} + +int sound_write(void *inst, int16_t **samples, int num, enum paging_signal *paging_signal, int *on, int channels) { sound_t *sound = (sound_t *)inst; int16_t buff[num << 1]; @@ -208,15 +256,22 @@ int sound_write(void *inst, int16_t **samples, int num, int channels) int i, ii; if (sound->pchannels == 2) { - if (channels < 2) { + if (paging_signal && on && paging_signal[0] != PAGING_SIGNAL_NONE) { + int16_t paging[num << 1]; + gen_paging_tone(sound, paging, num, paging_signal[0], on[0]); for (i = 0, ii = 0; i < num; i++) { buff[ii++] = samples[0][i]; + buff[ii++] = paging[i]; + } + } else if (channels == 2) { + for (i = 0, ii = 0; i < num; i++) { buff[ii++] = samples[0][i]; + buff[ii++] = samples[1][i]; } } else { for (i = 0, ii = 0; i < num; i++) { buff[ii++] = samples[0][i]; - buff[ii++] = samples[1][i]; + buff[ii++] = samples[0][i]; } } rc = snd_pcm_writei(sound->phandle, buff, num); diff --git a/src/nmt/nmt.c b/src/nmt/nmt.c index db764ec..5076fd6 100644 --- a/src/nmt/nmt.c +++ b/src/nmt/nmt.c @@ -334,7 +334,7 @@ int nmt_create(int channel, enum nmt_chan_type chan_type, const char *audiodev, PDEBUG(DNMT, DEBUG_DEBUG, "Creating 'NMT' instance for channel = %d (sample rate %d).\n", channel, samplerate); /* init general part of transceiver */ - rc = sender_create(&nmt->sender, channel, nmt_channel2freq(channel, 0), nmt_channel2freq(channel, 1), audiodev, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PILOT_SIGNAL_NONE); + rc = sender_create(&nmt->sender, channel, nmt_channel2freq(channel, 0), nmt_channel2freq(channel, 1), audiodev, samplerate, rx_gain, pre_emphasis, de_emphasis, write_rx_wave, write_tx_wave, read_rx_wave, loopback, 0, PAGING_SIGNAL_NONE); if (rc < 0) { PDEBUG(DNMT, DEBUG_ERROR, "Failed to init transceiver process!\n"); goto error;