diff --git a/docs/c-netz.html b/docs/c-netz.html index 08d8344..7e19841 100644 --- a/docs/c-netz.html +++ b/docs/c-netz.html @@ -54,7 +54,7 @@ A caller must not know the location of the phone anymore to reach the right base
  • Channel spacing: 10 KHz and optionally 12.5 KHz
  • Voice modulation: FM
  • Signaling modulation: carrier FSK -
  • Frequency deviation: 2.5 KHz (FSK); 2.4 KHz (Voice) +
  • Frequency deviation: 2.5 KHz (FSK); 4 KHz (Voice)
  • Mobile station transmit power: 50 mW up to 15 Watts
  • Base station transmit power: 25 Watts
  • Features: Speech Compandor, Audio scrambling diff --git a/src/amps/amps.h b/src/amps/amps.h index 4e2aa81..279f571 100644 --- a/src/amps/amps.h +++ b/src/amps/amps.h @@ -135,14 +135,14 @@ typedef struct amps { goertzel_t sat_goertzel[5]; /* filter for SAT signal decoding */ sample_t *sat_filter_spl; /* array with sample buffer for supervisory detection */ int sat_filter_pos; /* current sample position in filter_spl */ - double sat_phaseshift256[3]; /* how much the phase of sine wave changes per sample */ - double sat_phase256; /* current phase */ + double sat_phaseshift65536[3]; /* how much the phase of sine wave changes per sample */ + double sat_phase65536; /* current phase */ int sat_detected; /* current detection state flag */ int sat_detect_count; /* current number of consecutive detections/losses */ int sig_detected; /* current detection state flag */ int sig_detect_count; /* current number of consecutive detections/losses */ - double test_phaseshift256; /* how much the phase of sine wave changes per sample */ - double test_phase256; /* current phase */ + double test_phaseshift65536; /* how much the phase of sine wave changes per sample */ + double test_phase65536; /* current phase */ transaction_t *trans_list; /* list of transactions */ diff --git a/src/amps/dsp.c b/src/amps/dsp.c index cf359d1..b79abc6 100644 --- a/src/amps/dsp.c +++ b/src/amps/dsp.c @@ -99,10 +99,13 @@ #define PI M_PI -#define BANDWIDTH 20000.0 /* maximum bandwidth */ -#define FSK_DEVIATION 32767.0 /* +-8 KHz */ -#define SAT_DEVIATION 8192.0 /* +-2 KHz */ -#define COMPANDOR_0DB 45000 /* works quite well */ +#define MAX_DEVIATION 8000.0 +#define MAX_MODULATION 10000.0 +#define DBM0_DEVIATION 2900.0 /* deviation of dBm0 at 1 kHz */ +#define COMPANDOR_0DB 1.0 /* A level of 0dBm (1.0) shall be unaccected */ +#define FSK_DEVIATION (8000.0 / DBM0_DEVIATION) /* no emphasis */ +#define SAT_DEVIATION (2000.0 / DBM0_DEVIATION) /* no emphasis */ +#define MAX_DISPLAY (8000.0 / DBM0_DEVIATION) /* no emphasis */ #define BITRATE 10000 #define SIG_TONE_CROSSINGS 2000 /* 2000 crossings are 100ms @ 10 KHz */ #define SIG_TONE_MINBITS 950 /* minimum bit durations to detect signaling tone (1000 is perfect for 100 ms) */ @@ -116,7 +119,7 @@ #define CUT_OFF_HIGHPASS 300.0 /* cut off frequency for high pass filter to remove dc level from sound card / sample */ #define BEST_QUALITY 0.68 /* Best possible RX quality */ -static int16_t ramp_up[256], ramp_down[256]; +static sample_t ramp_up[256], ramp_down[256]; static double sat_freq[5] = { 5970.0, @@ -126,8 +129,8 @@ static double sat_freq[5] = { 10000.0, /* signaling tone */ }; -static int dsp_sine_sat[256]; -static int dsp_sine_test[256]; +static sample_t dsp_sine_sat[65536]; +static sample_t dsp_sine_test[65536]; static uint8_t dsp_sync_check[0x800]; @@ -138,10 +141,10 @@ void dsp_init(void) double s; PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine table for SAT signal.\n"); - for (i = 0; i < 256; i++) { - s = sin((double)i / 256.0 * 2.0 * PI); - dsp_sine_sat[i] = (int)(s * SAT_DEVIATION); - dsp_sine_test[i] = (int)(s * FSK_DEVIATION); + for (i = 0; i < 65536; i++) { + s = sin((double)i / 65536.0 * 2.0 * PI); + dsp_sine_sat[i] = s * SAT_DEVIATION; + dsp_sine_test[i] = s * FSK_DEVIATION; } /* sync checker */ @@ -170,7 +173,7 @@ static void dsp_init_ramp(amps_t *amps) else c = sqrt(c); #endif - ramp_down[i] = (int)(c * (double)amps->fsk_deviation); + ramp_down[i] = c * (double)amps->fsk_deviation; ramp_up[i] = -ramp_down[i]; } } @@ -190,9 +193,8 @@ int dsp_init_sender(amps_t *amps, int tolerant) PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for transceiver.\n"); - /* set deviation and modulation parameters */ - amps->sender.bandwidth = BANDWIDTH; - amps->sender.sample_deviation = 8000.0 / (double)FSK_DEVIATION; + /* set modulation parameters */ + sender_set_fm(&s->sender, MAX_DEVIATION, MAX_MODULATION, DBM0_DEVIATION, MAX_DISPLAY); if (amps->sender.samplerate < 96000) { PDEBUG(DDSP, DEBUG_ERROR, "Sample rate must be at least 96000 Hz to process FSK and SAT signals.\n"); @@ -229,7 +231,7 @@ int dsp_init_sender(amps_t *amps, int tolerant) amps->fsk_rx_window = spl; /* create devation and ramp */ - amps->fsk_deviation = FSK_DEVIATION; /* be sure not to overflow 32767 */ + amps->fsk_deviation = FSK_DEVIATION; dsp_init_ramp(amps); /* allocate ring buffer for SAT signal detection */ @@ -245,15 +247,15 @@ int dsp_init_sender(amps_t *amps, int tolerant) for (i = 0; i < 5; i++) { audio_goertzel_init(&s->sat_goertzel[i], sat_freq[i], amps->sender.samplerate); if (i < 3) { - amps->sat_phaseshift256[i] = 256.0 / ((double)amps->sender.samplerate / sat_freq[i]); - PDEBUG(DDSP, DEBUG_DEBUG, "sat_phaseshift256[%d] = %.4f\n", i, amps->sat_phaseshift256[i]); + amps->sat_phaseshift65536[i] = 65536.0 / ((double)amps->sender.samplerate / sat_freq[i]); + PDEBUG(DDSP, DEBUG_DEBUG, "sat_phaseshift65536[%d] = %.4f\n", i, amps->sat_phaseshift65536[i]); } } sat_reset(amps, "Initial state"); /* test tone */ - amps->test_phaseshift256 = 256.0 / ((double)amps->sender.samplerate / 1000.0); - PDEBUG(DDSP, DEBUG_DEBUG, "test_phaseshift256 = %.4f\n", amps->test_phaseshift256); + amps->test_phaseshift65536 = 65536.0 / ((double)amps->sender.samplerate / 1000.0); + PDEBUG(DDSP, DEBUG_DEBUG, "test_phaseshift65536 = %.4f\n", amps->test_phaseshift65536); /* be more tolerant when syncing */ amps->fsk_rx_sync_tolerant = tolerant; @@ -401,7 +403,7 @@ again: //printf("pos=%d length=%d copy=%d\n", pos, length, copy); for (i = 0; i < copy; i++) { #ifdef DEBUG_ENCODER - puts(debug_amplitude((double)spl[pos] / 32767.0)); + puts(debug_amplitude((double)spl[pos])); #endif *samples++ = spl[pos++]; } @@ -422,26 +424,19 @@ done: static void sat_encode(amps_t *amps, sample_t *samples, int length) { double phaseshift, phase; - int32_t sample; int i; - phaseshift = amps->sat_phaseshift256[amps->sat]; - phase = amps->sat_phase256; + phaseshift = amps->sat_phaseshift65536[amps->sat]; + phase = amps->sat_phase65536; for (i = 0; i < length; i++) { - sample = *samples; - sample += dsp_sine_sat[(uint8_t)phase]; - if (sample > 32767) - sample = 32767; - else if (sample < -32767) - sample = -32767; - *samples++ = sample; + *samples++ += dsp_sine_sat[(uint16_t)phase]; phase += phaseshift; - if (phase >= 256) - phase -= 256; + if (phase >= 65536) + phase -= 65536; } - amps->sat_phase256 = phase; + amps->sat_phase65536 = phase; } static void test_tone_encode(amps_t *amps, sample_t *samples, int length) @@ -449,17 +444,17 @@ static void test_tone_encode(amps_t *amps, sample_t *samples, int length) double phaseshift, phase; int i; - phaseshift = amps->test_phaseshift256; - phase = amps->test_phase256; + phaseshift = amps->test_phaseshift65536; + phase = amps->test_phase65536; for (i = 0; i < length; i++) { - *samples++ = dsp_sine_test[(uint8_t)phase]; + *samples++ = dsp_sine_test[(uint16_t)phase]; phase += phaseshift; - if (phase >= 256) - phase -= 256; + if (phase >= 65536) + phase -= 65536; } - amps->test_phase256 = phase; + amps->test_phase65536 = phase; } /* Provide stream of audio toward radio unit */ @@ -735,9 +730,9 @@ static void sat_decode(amps_t *amps, sample_t *samples, int length) if (quality[1] < 0) quality[1] = 0; - PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "SAT level %.2f%% quality %.0f%%\n", result[0] * 32767.0 / SAT_DEVIATION / 0.63662 * 100.0, quality[0] * 100.0); + PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "SAT level %.2f%% quality %.0f%%\n", result[0] / SAT_DEVIATION / 0.63662 * 100.0, quality[0] * 100.0); if (amps->sender.loopback || debuglevel == DEBUG_DEBUG) { - PDEBUG_CHAN(DDSP, debuglevel, "Signaling Tone level %.2f%% quality %.0f%%\n", result[2] * 32767.0 / FSK_DEVIATION / 0.63662 * 100.0, quality[1] * 100.0); + PDEBUG_CHAN(DDSP, debuglevel, "Signaling Tone level %.2f%% quality %.0f%%\n", result[2] / FSK_DEVIATION / 0.63662 * 100.0, quality[1] * 100.0); } if (quality[0] > SAT_QUALITY) { if (amps->sat_detected == 0) { diff --git a/src/anetz/anetz.h b/src/anetz/anetz.h index 05d8e50..aee43ef 100644 --- a/src/anetz/anetz.h +++ b/src/anetz/anetz.h @@ -33,12 +33,12 @@ typedef struct anetz { int fsk_filter_pos; /* current sample position in filter_spl */ int tone_detected; /* what tone has been detected */ int tone_count; /* how long has that tone been detected */ - double tone_phaseshift256; /* how much the phase of sine wave changes per sample */ - double tone_phase256; /* current phase */ + double tone_phaseshift65536; /* how much the phase of sine wave changes per sample */ + double tone_phase65536; /* current phase */ double page_gain; /* factor to raise the paging tones */ int page_sequence; /* if set, use paging tones in sequence rather than parallel */ - double paging_phaseshift256[4];/* how much the phase of sine wave changes per sample */ - double paging_phase256[4]; /* current phase */ + double paging_phaseshift65536[4];/* how much the phase of sine wave changes per sample */ + double paging_phase65536[4]; /* current phase */ int paging_tone; /* current tone (0..3) in sequenced mode */ int paging_count; /* current sample count of tone in seq. mode */ int paging_transition; /* set to number of samples during transition */ diff --git a/src/anetz/dsp.c b/src/anetz/dsp.c index 1200c43..65db940 100644 --- a/src/anetz/dsp.c +++ b/src/anetz/dsp.c @@ -35,8 +35,12 @@ #define PI 3.1415927 /* signaling */ -#define BANDWIDTH 15000.0 /* maximum bandwidth */ -#define TX_PEAK_TONE 8192.0 /* peak amplitude for all tones */ +#define MAX_DEVIATION 15000.0 +#define MAX_MODULATION 4000.0 +#define DBM0_DEVIATION 10500.0 /* deviation of dBm0 at 1 kHz */ +#define TX_PEAK_TONE (10500.0 / DBM0_DEVIATION) /* 10.5 kHz, no emphasis */ +#define TX_PEAK_PAGE (15000.0 / DBM0_DEVIATION) /* 15 kHz, no emphasis */ +#define MAX_DISPLAY (15000.0 / DBM0_DEVIATION) /* 15 kHz, no emphasis */ #define CHUNK_DURATION 0.010 /* 10 ms */ // FIXME: how long until we detect a tone? @@ -53,7 +57,8 @@ static double fsk_tones[2] = { }; /* table for fast sine generation */ -sample_t dsp_sine_tone[256]; +static sample_t dsp_sine_tone[65536]; +static sample_t dsp_sine_page[65536]; /* global init for audio processing */ void dsp_init(void) @@ -62,14 +67,10 @@ void dsp_init(void) double s; PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine tables.\n"); - for (i = 0; i < 256; i++) { - s = sin((double)i / 256.0 * 2.0 * PI); - dsp_sine_tone[i] = (int)(s * TX_PEAK_TONE); - } - - if (TX_PEAK_TONE > 32767.0) { - fprintf(stderr, "TX_PEAK_TONE definition too high, please fix!\n"); - abort(); + for (i = 0; i < 65536; i++) { + s = sin((double)i / 65536.0 * 2.0 * PI); + dsp_sine_tone[i] = s * TX_PEAK_TONE; + dsp_sine_page[i] = s * TX_PEAK_PAGE; } } @@ -82,15 +83,10 @@ int dsp_init_sender(anetz_t *anetz, double page_gain, int page_sequence) PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for 'Sender'.\n"); - /* set deviation and modulation parameters */ - anetz->sender.bandwidth = BANDWIDTH; - anetz->sender.sample_deviation = 11000.0 / (double)TX_PEAK_TONE; + /* set modulation parameters */ + sender_set_fm(&anetz->sender, MAX_DEVIATION * page_gain, MAX_MODULATION, DBM0_DEVIATION, MAX_DISPLAY); anetz->page_gain = page_gain; - if (page_gain * TX_PEAK_TONE > 32767.0) { - page_gain = 32767.0 / TX_PEAK_TONE; - PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Highest possible gain of paging tones is %.1f dB.\n", log10(page_gain) * 20); - } anetz->page_sequence = page_sequence; audio_init_loss(&anetz->sender.loss, LOSS_INTERVAL, anetz->sender.loss_volume, LOSS_TIME); @@ -109,8 +105,8 @@ int dsp_init_sender(anetz_t *anetz, double page_gain, int page_sequence) for (i = 0; i < 2; i++) audio_goertzel_init(&anetz->fsk_tone_goertzel[i], fsk_tones[i], anetz->sender.samplerate); tone = fsk_tones[(anetz->sender.loopback == 0) ? 0 : 1]; - anetz->tone_phaseshift256 = 256.0 / ((double)anetz->sender.samplerate / tone); - PDEBUG(DDSP, DEBUG_DEBUG, "TX %.0f Hz phaseshift = %.4f\n", tone, anetz->tone_phaseshift256); + anetz->tone_phaseshift65536 = 65536.0 / ((double)anetz->sender.samplerate / tone); + PDEBUG(DDSP, DEBUG_DEBUG, "TX %.0f Hz phaseshift = %.4f\n", tone, anetz->tone_phaseshift65536); return 0; } @@ -169,19 +165,19 @@ static void fsk_decode_chunk(anetz_t *anetz, sample_t *spl, int max) /* show quality of tone */ if (anetz->sender.loopback) { /* adjust level, so we get peak of sine curve */ - PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[1], level / 0.63662 * 100.0 * 32768.0 / TX_PEAK_TONE, result[1] / level * 100.0); + PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[1], level / 0.63662 * 100.0 / TX_PEAK_TONE, result[1] / level * 100.0); } if (level / 0.63 > 0.05 && result[0] / level > 0.5) - PDEBUG_CHAN(DDSP, DEBUG_INFO, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[0], level / 0.63662 * 100.0 * 32768.0 / TX_PEAK_TONE, result[0] / level * 100.0); + PDEBUG_CHAN(DDSP, DEBUG_INFO, "Tone %.0f: Level=%3.0f%% Quality=%3.0f%%\n", fsk_tones[0], level / 0.63662 * 100.0 / TX_PEAK_TONE, result[0] / level * 100.0); /* adjust level, so we get peak of sine curve */ /* indicate detected tone */ if (level / 0.63 > 0.05 && result[0] / level > 0.5) - fsk_receive_tone(anetz, 0, 1, level / 0.63662 * 32768.0 / TX_PEAK_TONE); + fsk_receive_tone(anetz, 0, 1, level / 0.63662 / TX_PEAK_TONE); else if (level / 0.63 > 0.05 && result[1] / level > 0.5) - fsk_receive_tone(anetz, 1, 1, level / 0.63662 * 32768.0 / TX_PEAK_TONE); + fsk_receive_tone(anetz, 1, 1, level / 0.63662 / TX_PEAK_TONE); else - fsk_receive_tone(anetz, -1, 0, level / 0.63662 * 32768.0 / TX_PEAK_TONE); + fsk_receive_tone(anetz, -1, 0, level / 0.63662 / TX_PEAK_TONE); } /* Process received audio stream from radio unit. */ @@ -230,42 +226,36 @@ void dsp_set_paging(anetz_t *anetz, double *freq) int i; for (i = 0; i < 4; i++) { - anetz->paging_phaseshift256[i] = 256.0 / ((double)anetz->sender.samplerate / freq[i]); - anetz->paging_phase256[i] = 0; + anetz->paging_phaseshift65536[i] = 65536.0 / ((double)anetz->sender.samplerate / freq[i]); + anetz->paging_phase65536[i] = 0; } } /* Generate audio stream of 4 simultanious paging tones. Keep phase for next call of function. - * Use TX_PEAK_TONE*page_gain for all tones, which gives peak of 1/4th for each individual tone. */ + * Use TX_PEAK_PAGE*page_gain for all tones, which gives peak of 1/4th for each individual tone. */ static void fsk_paging_tone(anetz_t *anetz, sample_t *samples, int length) { - double phaseshift[4], phase[4]; + double *phaseshift, *phase; int i; double sample; - for (i = 0; i < 4; i++) { - phaseshift[i] = anetz->paging_phaseshift256[i]; - phase[i] = anetz->paging_phase256[i]; - } + phaseshift = anetz->paging_phaseshift65536; + phase = anetz->paging_phase65536; for (i = 0; i < length; i++) { - sample = (int32_t)dsp_sine_tone[(uint8_t)phase[0]] - + (int32_t)dsp_sine_tone[(uint8_t)phase[1]] - + (int32_t)dsp_sine_tone[(uint8_t)phase[2]] - + (int32_t)dsp_sine_tone[(uint8_t)phase[3]]; + sample = dsp_sine_page[(uint16_t)phase[0]] + + dsp_sine_page[(uint16_t)phase[1]] + + dsp_sine_page[(uint16_t)phase[2]] + + dsp_sine_page[(uint16_t)phase[3]]; *samples++ = sample / 4.0 * anetz->page_gain; phase[0] += phaseshift[0]; phase[1] += phaseshift[1]; phase[2] += phaseshift[2]; phase[3] += phaseshift[3]; - if (phase[0] >= 256) phase[0] -= 256; - if (phase[1] >= 256) phase[1] -= 256; - if (phase[2] >= 256) phase[2] -= 256; - if (phase[3] >= 256) phase[3] -= 256; - } - - for (i = 0; i < 4; i++) { - anetz->paging_phase256[i] = phase[i]; + if (phase[0] >= 65536) phase[0] -= 65536; + if (phase[1] >= 65536) phase[1] -= 65536; + if (phase[2] >= 65536) phase[2] -= 65536; + if (phase[3] >= 65536) phase[3] -= 65536; } } @@ -280,14 +270,11 @@ static void fsk_paging_tone(anetz_t *anetz, sample_t *samples, int length) */ static void fsk_paging_tone_sequence(anetz_t *anetz, sample_t *samples, int length, int numspl) { - double phaseshift[4], phase[4]; - int i; + double *phaseshift, *phase; int tone, count, transition; - for (i = 0; i < 4; i++) { - phaseshift[i] = anetz->paging_phaseshift256[i]; - phase[i] = anetz->paging_phase256[i]; - } + phaseshift = anetz->paging_phaseshift65536; + phase = anetz->paging_phase65536; tone = anetz->paging_tone; count = anetz->paging_count; transition = anetz->paging_transition; @@ -295,21 +282,21 @@ static void fsk_paging_tone_sequence(anetz_t *anetz, sample_t *samples, int leng while (length) { /* use tone, but during transition of tones, keep phase 0 degrees (high level) until next tone reaches 0 degrees (high level) */ if (!transition) - *samples++ = dsp_sine_tone[(uint8_t)phase[tone]] * anetz->page_gain; + *samples++ = dsp_sine_page[(uint16_t)phase[tone]] * anetz->page_gain; else { /* fade between old an new tone */ *samples++ - = (double)dsp_sine_tone[(uint8_t)phase[(tone - 1) & 3]] * (double)(transition - count) / (double)transition / 2.0 * anetz->page_gain - + (double)dsp_sine_tone[(uint8_t)phase[tone]] * (double)count / (double)transition / 2.0 * anetz->page_gain; + = (double)dsp_sine_page[(uint16_t)phase[(tone - 1) & 3]] * (double)(transition - count) / (double)transition / 2.0 * anetz->page_gain + + (double)dsp_sine_page[(uint16_t)phase[tone]] * (double)count / (double)transition / 2.0 * anetz->page_gain; } phase[0] += phaseshift[0]; phase[1] += phaseshift[1]; phase[2] += phaseshift[2]; phase[3] += phaseshift[3]; - if (phase[0] >= 256) phase[0] -= 256; - if (phase[1] >= 256) phase[1] -= 256; - if (phase[2] >= 256) phase[2] -= 256; - if (phase[3] >= 256) phase[3] -= 256; + if (phase[0] >= 65536) phase[0] -= 65536; + if (phase[1] >= 65536) phase[1] -= 65536; + if (phase[2] >= 65536) phase[2] -= 65536; + if (phase[3] >= 65536) phase[3] -= 65536; count++; if (transition && count == transition) { transition = 0; @@ -327,9 +314,6 @@ static void fsk_paging_tone_sequence(anetz_t *anetz, sample_t *samples, int leng length--; } - for (i = 0; i < 4; i++) { - anetz->paging_phase256[i] = phase[i]; - } anetz->paging_tone = tone; anetz->paging_count = count; anetz->paging_transition = transition; @@ -341,17 +325,17 @@ static void fsk_tone(anetz_t *anetz, sample_t *samples, int length) double phaseshift, phase; int i; - phaseshift = anetz->tone_phaseshift256; - phase = anetz->tone_phase256; + phaseshift = anetz->tone_phaseshift65536; + phase = anetz->tone_phase65536; for (i = 0; i < length; i++) { - *samples++ = dsp_sine_tone[(uint8_t)phase]; + *samples++ = dsp_sine_tone[(uint16_t)phase]; phase += phaseshift; - if (phase >= 256) - phase -= 256; + if (phase >= 65536) + phase -= 65536; } - anetz->tone_phase256 = phase; + anetz->tone_phase65536 = phase; } /* Provide stream of audio toward radio unit */ diff --git a/src/bnetz/bnetz.h b/src/bnetz/bnetz.h index 3ba4b51..176abfd 100644 --- a/src/bnetz/bnetz.h +++ b/src/bnetz/bnetz.h @@ -88,8 +88,8 @@ typedef struct bnetz { int fsk_filter_qualidx; /* index of quality array above */ int tone_detected; /* what tone has been detected */ int tone_count; /* how long has that tone been detected */ - double phaseshift256[2]; /* how much the phase of sine wave changes per sample */ - double phase256; /* current phase */ + double phaseshift65536[2]; /* how much the phase of sine wave changes per sample */ + double phase65536; /* current phase */ int telegramm; /* set, if there is a valid telegram */ sample_t *telegramm_spl; /* 16 * samples_per_bit */ int telegramm_pos; /* current sample position in telegramm_spl */ diff --git a/src/bnetz/dsp.c b/src/bnetz/dsp.c index 95a78d6..70b4649 100644 --- a/src/bnetz/dsp.c +++ b/src/bnetz/dsp.c @@ -34,9 +34,19 @@ #define PI 3.1415927 +/* Notes on TX_PEAK_TONE level: + * + * At 2000 Hz the deviation shall be 4 kHz, so with emphasis the deviation + * at 1000 Hz would be theoretically 2 kHz. This is factor 0.714 below + * 2.8 kHz deviation we want at dBm0. + */ + /* signaling */ -#define BANDWIDTH 5000.0 /* maximum bandwidth */ -#define TX_PEAK_TONE 5000.0 /* peak amplitude for all tones */ +#define MAX_DEVIATION 4000.0 +#define MAX_MODULATION 3000.0 +#define DBM0_DEVIATION 2800.0 /* deviation of dBm0 at 1 kHz */ +#define TX_PEAK_TONE (4000.0 / 2000.0 * 1000.0 / DBM0_DEVIATION) +#define MAX_DISPLAY 1.4 /* something above dBm0 */ #define BIT_DURATION 0.010 /* bit length: 10 ms */ #define FILTER_STEP 0.001 /* step every 1 ms */ #define METERING_HZ 2900 /* metering pulse frequency */ @@ -54,7 +64,7 @@ static double fsk_bits[2] = { }; /* table for fast sine generation */ -static sample_t dsp_sine[256]; +static sample_t dsp_sine[65536]; /* global init for FSK */ void dsp_init(void) @@ -62,13 +72,8 @@ void dsp_init(void) int i; PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine table.\n"); - for (i = 0; i < 256; i++) { - dsp_sine[i] = (int)(sin((double)i / 256.0 * 2.0 * PI) * TX_PEAK_TONE); - } - - if (TX_PEAK_TONE > 32767.0) { - fprintf(stderr, "TX_PEAK_TONE definition too high, please fix!\n"); - abort(); + for (i = 0; i < 65536; i++) { + dsp_sine[i] = sin((double)i / 65536.0 * 2.0 * PI) * TX_PEAK_TONE; } } @@ -85,9 +90,8 @@ int dsp_init_sender(bnetz_t *bnetz) PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for 'Sender'.\n"); - /* set deviation and modulation parameters */ - bnetz->sender.bandwidth = BANDWIDTH; - bnetz->sender.sample_deviation = 1250.0 / (double)TX_PEAK_TONE; // FIXME: calc real value + /* set modulation parameters */ + sender_set_fm(&bnetz->sender, MAX_DEVIATION, MAX_MODULATION, DBM0_DEVIATION, MAX_DISPLAY); audio_init_loss(&bnetz->sender.loss, LOSS_INTERVAL, bnetz->sender.loss_volume, LOSS_TIME); @@ -114,8 +118,8 @@ int dsp_init_sender(bnetz_t *bnetz) /* count symbols */ for (i = 0; i < 2; i++) { audio_goertzel_init(&bnetz->fsk_goertzel[i], fsk_bits[i], bnetz->sender.samplerate); - bnetz->phaseshift256[i] = 256.0 / ((double)bnetz->sender.samplerate / fsk_bits[i]); - PDEBUG(DDSP, DEBUG_DEBUG, "phaseshift[%d] = %.4f (must be arround 64 at 8000hz)\n", i, bnetz->phaseshift256[i]); + bnetz->phaseshift65536[i] = 65536.0 / ((double)bnetz->sender.samplerate / fsk_bits[i]); + PDEBUG(DDSP, DEBUG_DEBUG, "phaseshift[%d] = %.4f (must be arround 64 at 8000hz)\n", i, bnetz->phaseshift65536[i]); } return 0; @@ -241,9 +245,9 @@ static inline void fsk_decode_step(bnetz_t *bnetz, int pos) // FIXME: better threshold /* adjust level, so we get peak of sine curve */ if (level / 0.63 > 0.05 && (softbit > 0.75 || softbit < 0.25)) { - fsk_receive_tone(bnetz, bit, 1, level / 0.63662 * 32768.0 / TX_PEAK_TONE, quality); + fsk_receive_tone(bnetz, bit, 1, level / 0.63662 / TX_PEAK_TONE, quality); } else - fsk_receive_tone(bnetz, bit, 0, level / 0.63662 * 32768.0 / TX_PEAK_TONE, quality); + fsk_receive_tone(bnetz, bit, 0, level / 0.63662 / TX_PEAK_TONE, quality); if (bnetz->fsk_filter_bit != bit) { /* if we have a bit change, reset sample counter to one half bit duration */ @@ -256,7 +260,7 @@ static inline void fsk_decode_step(bnetz_t *bnetz, int pos) printf("|%s|\n", debug_amplitude(quality); #endif /* adjust level, so we get peak of sine curve */ - fsk_receive_bit(bnetz, bit, level / 0.63662 * 32768.0 / TX_PEAK_TONE, quality); + fsk_receive_bit(bnetz, bit, level / 0.63662 / TX_PEAK_TONE, quality); bnetz->fsk_filter_sample = 10; } } @@ -308,17 +312,17 @@ static void fsk_tone(bnetz_t *bnetz, sample_t *samples, int length, int tone) double phaseshift, phase; int i; - phase = bnetz->phase256; - phaseshift = bnetz->phaseshift256[tone]; + phase = bnetz->phase65536; + phaseshift = bnetz->phaseshift65536[tone]; for (i = 0; i < length; i++) { - *samples++ = dsp_sine[(uint8_t)phase]; + *samples++ = dsp_sine[(uint16_t)phase]; phase += phaseshift; - if (phase >= 256) - phase -= 256; + if (phase >= 65536) + phase -= 65536; } - bnetz->phase256 = phase; + bnetz->phase65536 = phase; } static int fsk_telegramm(bnetz_t *bnetz, sample_t *samples, int length) @@ -342,17 +346,17 @@ next_telegramm: bnetz->telegramm_pos = 0; spl = bnetz->telegramm_spl; /* render telegramm */ - phase = bnetz->phase256; + phase = bnetz->phase65536; for (i = 0; i < 16; i++) { - phaseshift = bnetz->phaseshift256[telegramm[i] == '1']; + phaseshift = bnetz->phaseshift65536[telegramm[i] == '1']; for (j = 0; j < bnetz->samples_per_bit; j++) { - *spl++ = dsp_sine[(uint8_t)phase]; + *spl++ = dsp_sine[(uint16_t)phase]; phase += phaseshift; - if (phase >= 256) - phase -= 256; + if (phase >= 65536) + phase -= 65536; } } - bnetz->phase256 = phase; + bnetz->phase65536 = phase; } /* send audio from telegramm */ diff --git a/src/cnetz/dsp.c b/src/cnetz/dsp.c index a927c55..1fc404a 100644 --- a/src/cnetz/dsp.c +++ b/src/cnetz/dsp.c @@ -43,9 +43,12 @@ extern int voice_deviation; #define PI M_PI -#define BANDWIDTH 5500.0 /* maximum bandwidth */ -#define FSK_DEVIATION 10000 -#define COMPANDOR_0DB 30000 +#define MAX_DEVIATION 4000.0 +#define MAX_MODULATION 5280.0 +#define DBM0_DEVIATION 4000.0 /* deviation of dBm0 at 1 kHz */ +#define COMPANDOR_0DB 1.0 /* A level of 0dBm (1.0) shall be unaccected */ +#define FSK_DEVIATION (2500.0 / DBM0_DEVIATION) /* no emphasis */ +#define MAX_DISPLAY 1.4 /* something above dBm0, no emphasis */ #define BITRATE 5280.0 /* bits per second */ #define BLOCK_BITS 198 /* duration of one time slot including pause at beginning and end */ #define CUT_OFF_OFFSET 300.0 /* cut off frequency for offset filter (level correction between subsequent audio chunks) */ @@ -76,7 +79,7 @@ static void dsp_init_ramp(cnetz_t *cnetz) c = -sqrt(-c); else c = sqrt(c); - ramp_down[i] = (int)(c * (double)cnetz->fsk_deviation); + ramp_down[i] = c * (double)cnetz->fsk_deviation; ramp_up[i] = -ramp_down[i]; } } @@ -90,9 +93,8 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], do PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init FSK for 'Sender'.\n"); - /* set deviation and modulation parameters */ - cnetz->sender.bandwidth = BANDWIDTH; - cnetz->sender.sample_deviation = 2500.0 / (double)FSK_DEVIATION; + /* set modulation parameters */ + sender_set_fm(&cnetz->sender, MAX_DEVIATION, MAX_MODULATION, DBM0_DEVIATION, MAX_DISPLAY); if (measure_speed) { cnetz->measure_speed = measure_speed; @@ -119,7 +121,7 @@ int dsp_init_sender(cnetz_t *cnetz, int measure_speed, double clock_speed[2], do } /* create devation and ramp */ - cnetz->fsk_deviation = FSK_DEVIATION; /* be sure not to overflow -32767 .. 32767 */ + cnetz->fsk_deviation = FSK_DEVIATION; dsp_init_ramp(cnetz); cnetz->fsk_noise = noise; @@ -465,7 +467,7 @@ static int fsk_distributed_encode(cnetz_t *cnetz, const char *bits) } while (phase < 256.0); phase -= 256.0; } - *marker = -32768; /* indicator for inserting speech */ + *marker = 999; /* marker for inserting speech */ } /* add 46 * (1+4+1 + 60) bits */ for (i = 0; i < 46; i++) { @@ -556,7 +558,7 @@ static int fsk_distributed_encode(cnetz_t *cnetz, const char *bits) } while (phase < 256.0); phase -= 256.0; } - *marker = -32768; /* indicator for inserting speech */ + *marker = 999; /* marker for inserting speech */ } /* depending on the number of samples, return the number */ @@ -706,7 +708,7 @@ again: if (length - count < copy) copy = length - count; for (i = 0; i < copy; i++) { - if (*spl == -32768) { + if (*spl == 999) { /* marker found to insert new chunk of audio */ jitter_load(&cnetz->sender.dejitter, speech_buffer, 100); /* 1. compress dynamics */ @@ -722,15 +724,9 @@ again: pre_emphasis(&cnetz->estate, speech_buffer, speech_length); /* change level */ if (voice_deviation != 1) { - int sample, j; - for (j = 0; j < speech_length; j++) { - sample = speech_buffer[j] * voice_deviation; - if (sample > 32767) - sample = 32767; - if (sample < -32768) - sample = -32768; - speech_buffer[j] = sample; - } + int j; + for (j = 0; j < speech_length; j++) + speech_buffer[j] *= (double)voice_deviation; } speech_pos = 0; } @@ -801,7 +797,7 @@ void unshrink_speech(cnetz_t *cnetz, sample_t *speech_buffer, int count) factor = cnetz->offset_factor; for (i = 0; i < count; i++) { /* change level */ - x = speech_buffer[i] / voice_deviation; + x = speech_buffer[i] / (double)voice_deviation; /* high-pass to remove low level frequencies, caused by level jump between audio chunks */ y = factor * (y_last + x - x_last); x_last = x; diff --git a/src/cnetz/fsk_fm_demod.c b/src/cnetz/fsk_fm_demod.c index 74dd8ab..c151fb7 100644 --- a/src/cnetz/fsk_fm_demod.c +++ b/src/cnetz/fsk_fm_demod.c @@ -148,7 +148,7 @@ int fsk_fm_init(fsk_fm_demod_t *fsk, cnetz_t *cnetz, int samplerate, double bitr goto error; } - fsk->level_threshold = 655; + fsk->level_threshold = 0.1; return 0; @@ -170,9 +170,10 @@ void fsk_fm_exit(fsk_fm_demod_t *fsk) } /* get levels, sync time and jitter from sync sequence or frame data */ -static inline void get_levels(fsk_fm_demod_t *fsk, int *_min, int *_max, int *_avg, int *_probes, int num, double *_time, double *_jitter) +static inline void get_levels(fsk_fm_demod_t *fsk, double *_min, double *_max, double *_avg, int *_probes, int num, double *_time, double *_jitter) { - int min = 32767, max = -32768, avg = 0, count = 0, level; + int count = 0; + double min = 0, max = 0, avg = 0, level; double time = 0, t, sync_average, sync_time, jitter = 0; int bit_offset; int i; @@ -192,19 +193,20 @@ static inline void get_levels(fsk_fm_demod_t *fsk, int *_min, int *_max, int *_a if (t > BITS_PER_SUPERFRAME / 2) t -= BITS_PER_SUPERFRAME; //if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V) -// printf("%d: level=%d%% @%.2f difference=%.2f\n", bit_offset, level * 100 / 65536, fsk->change_when[(fsk->change_pos - 1 - i) & 0xff], t); +// printf("%d: level=%.0f%% @%.2f difference=%.2f\n", bit_offset, level * 100, fsk->change_when[(fsk->change_pos - 1 - i) & 0xff], t); time += t; - if (level < min) + if (i == 0 || level < min) min = level; - if (level > max) + if (i == 0 || level > max) max = level; avg += level; count++; } + /* should never happen */ if (!count) { - *_min = *_max = *_avg = 0; + *_min = *_max = *_avg = 0.0; return; } @@ -219,7 +221,7 @@ static inline void get_levels(fsk_fm_demod_t *fsk, int *_min, int *_max, int *_a *_probes = count; *_min = min; *_max = max; - *_avg = avg / count; + *_avg = avg / (double)count; if (_time) { // if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V) @@ -254,15 +256,16 @@ static inline void get_levels(fsk_fm_demod_t *fsk, int *_min, int *_max, int *_a } } -static inline void got_bit(fsk_fm_demod_t *fsk, int bit, int change_level) +static inline void got_bit(fsk_fm_demod_t *fsk, int bit, double change_level) { - int min, max, avg, probes; + int probes; + double min, max, avg; /* count bits, but do not exceed 4 bits per SPK block */ if (fsk->cnetz->dsp_mode == DSP_MODE_SPK_V) { /* for first bit, we have only half of the modulation deviation, so we multiply level by two */ if (fsk->bit_count == 0) - change_level *= 2; + change_level *= 2.0; if (fsk->bit_count == 4) return; } @@ -284,20 +287,20 @@ static inline void got_bit(fsk_fm_demod_t *fsk, int bit, int change_level) * for all other bits in the sync sequence. * after sync, the theshold is set to half of the average of * all changes in the sync sequence */ - if (change_level) { - fsk->level_threshold = (double)change_level / 2.0; + if (change_level > 0.0) { + fsk->level_threshold = change_level / 2.0; } else if ((fsk->rx_sync & 0x1f) == 0x00 || (fsk->rx_sync & 0x1f) == 0x1f) { if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V) - fsk->level_threshold = 655; + fsk->level_threshold = 0.01; } if (detect_sync(fsk->rx_sync)) { fsk->sync = FSK_SYNC_POSITIVE; got_sync: get_levels(fsk, &min, &max, &avg, &probes, 30, &fsk->sync_time, &fsk->sync_jitter); - fsk->sync_level = (double)avg / 65535.0; + fsk->sync_level = avg / 2.0; if (fsk->sync == FSK_SYNC_NEGATIVE) fsk->sync_level = -fsk->sync_level; -// printf("sync (change min=%d%% max=%d%% avg=%d%% sync_time=%.2f jitter=%.2f probes=%d)\n", min * 100 / 65535, max * 100 / 65535, avg * 100 / 65535, fsk->sync_time, fsk->sync_jitter, probes); +// printf("sync (change min=%.0f%% max=%.0f%% avg=%.0f%% sync_time=%.2f jitter=%.2f probes=%d)\n", min * 100, max * 100, avg * 100, fsk->sync_time, fsk->sync_jitter, probes); fsk->level_threshold = (double)avg / 2.0; fsk->rx_sync = 0; fsk->rx_buffer_count = 0; @@ -342,6 +345,10 @@ static inline void find_change(fsk_fm_demod_t *fsk) change_at = -1; change_positive = -1; + /* get level range (level_min and level_max) and also + * get maximum slope (change_max) and where it was + * (change_at) and what direction it went (change_positive) + */ for (i = 0; i < fsk->bit_buffer_len; i++) { last_s = s; s = fsk->bit_buffer_spl[fsk->bit_buffer_pos++]; @@ -417,7 +424,7 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length) if (fsk->cnetz->dsp_mode != DSP_MODE_SPK_V) { #ifdef DEBUG_DECODER DEBUG_DECODER - puts(debug_amplitude(samples[i] / 32768.0)); + puts(debug_amplitude(samples[i])); #endif find_change(fsk); } else { @@ -441,7 +448,7 @@ void fsk_fm_demod(fsk_fm_demod_t *fsk, sample_t *samples, int length) if (t >= 0.5 && t < 5.5) { #ifdef DEBUG_DECODER DEBUG_DECODER - puts(debug_amplitude(samples[i] / 32768.0)); + puts(debug_amplitude(samples[i])); #endif find_change(fsk); } else diff --git a/src/cnetz/fsk_fm_demod.h b/src/cnetz/fsk_fm_demod.h index bf782e5..c8692c3 100644 --- a/src/cnetz/fsk_fm_demod.h +++ b/src/cnetz/fsk_fm_demod.h @@ -24,7 +24,7 @@ typedef struct fsk_fm_demod { int bit_buffer_len; /* number of samples in ring buffer */ int bit_buffer_half; /* half of ring buffer */ int bit_buffer_pos; /* current position to write next sample */ - int level_threshold; /* threshold for detection of next level change */ + double level_threshold; /* threshold for detection of next level change */ double bits_per_sample; /* duration of one sample in bits */ double next_bit; /* count time to detect bits */ int bit_count; /* counts bits, to match 4 bits at distributed signaling */ @@ -45,7 +45,7 @@ typedef struct fsk_fm_demod { int rx_buffer_count; /* counter when receiving bits */ /* statistics */ - int change_levels[256]; /* ring buffer to store levels */ + double change_levels[256]; /* ring buffer to store levels */ double change_when[256]; /* ring buffer to store time when level has changed */ uint8_t change_pos; /* index for next write */ } fsk_fm_demod_t; diff --git a/src/cnetz/scrambler.c b/src/cnetz/scrambler.c index 439e054..f5adc03 100644 --- a/src/cnetz/scrambler.c +++ b/src/cnetz/scrambler.c @@ -36,22 +36,22 @@ #define TEST_1000HZ_DB 55.0 /* sine wave for carrier to modulate to */ -static double carrier[256]; +static double carrier[65536]; void scrambler_init(void) { int i; - for (i = 0; i < 256; i++) { + for (i = 0; i < 65536; i++) { /* our amplitude must be doubled, since we have one spectrum above and one below carrier */ - carrier[i] = sin((double)i / 256.0 * 2 * PI) * 2.0; + carrier[i] = sin((double)i / 65536.0 * 2 * PI) * 2.0; } } void scrambler_setup(scrambler_t *scrambler, int samplerate) { filter_lowpass_init(&scrambler->lp, CARRIER_HZ - FILTER_BELOW, samplerate, FILTER_TURNS); - scrambler->carrier_phaseshift256 = 256.0 / ((double)samplerate / CARRIER_HZ); + scrambler->carrier_phaseshift65536 = 65536.0 / ((double)samplerate / CARRIER_HZ); } /* Modulate samples to carriere that is twice the mirror frequency. @@ -63,18 +63,18 @@ void scrambler(scrambler_t *scrambler, sample_t *samples, int length) double phaseshift, phase; int i; - phaseshift = scrambler->carrier_phaseshift256; - phase = scrambler->carrier_phase256; + phaseshift = scrambler->carrier_phaseshift65536; + phase = scrambler->carrier_phase65536; for (i = 0; i < length; i++) { /* modulate samples to carrier */ - samples[i] *= carrier[((uint8_t)phase) & 0xff]; + samples[i] *= carrier[(uint16_t)phase]; phase += phaseshift; - if (phase >= 256.0) - phase -= 256.0; + if (phase >= 65536.0) + phase -= 65536.0; } - scrambler->carrier_phase256 = phase; + scrambler->carrier_phase65536 = phase; /* cut off carrier frequency and modulation above carrier frequency */ filter_process(&scrambler->lp, samples, length); diff --git a/src/cnetz/scrambler.h b/src/cnetz/scrambler.h index ffc2d77..19adba7 100644 --- a/src/cnetz/scrambler.h +++ b/src/cnetz/scrambler.h @@ -1,8 +1,8 @@ #include "../common/filter.h" typedef struct scrambler { - double carrier_phaseshift256; /* carrier phase shift per sample */ - double carrier_phase256; /* current phase of carrier frequency */ + double carrier_phaseshift65536;/* carrier phase shift per sample */ + double carrier_phase65536; /* current phase of carrier frequency */ filter_t lp; /* filter to remove carrier frequency */ } scrambler_t; diff --git a/src/cnetz/telegramm.c b/src/cnetz/telegramm.c index 8edbb2e..e3565eb 100644 --- a/src/cnetz/telegramm.c +++ b/src/cnetz/telegramm.c @@ -1492,9 +1492,9 @@ void cnetz_decode_telegramm(cnetz_t *cnetz, const char *bits, double level, doub telegramm.jitter = jitter; if (bit_errors) - PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Jitter: %.2f Sync Time: %.2f (TS %.2f) Bit errors: %d %s\n", fabs(level) * 32767.0 / cnetz->fsk_deviation * 100.0, jitter, sync_time, sync_time / 396.0, bit_errors, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)"); + PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Jitter: %.2f Sync Time: %.2f (TS %.2f) Bit errors: %d %s\n", fabs(level) / cnetz->fsk_deviation * 100.0, jitter, sync_time, sync_time / 396.0, bit_errors, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)"); else - PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Jitter: %.2f Sync Time: %.2f (TS %.2f) %s\n", fabs(level) * 32767.0 / cnetz->fsk_deviation * 100.0, jitter, sync_time, sync_time / 396.0, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)"); + PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Jitter: %.2f Sync Time: %.2f (TS %.2f) %s\n", fabs(level) / cnetz->fsk_deviation * 100.0, jitter, sync_time, sync_time / 396.0, (level < 0) ? "NEGATIVE (phone's mode)" : "POSITIVE (base station's mode)"); if (cnetz->sender.loopback) { PDEBUG(DFRAME, DEBUG_NOTICE, "Received Telegramm in loopback test mode (opcode %d = %s)\n", opcode, definition_opcode[opcode].message_name); diff --git a/src/common/call.c b/src/common/call.c index f816417..ce4a3bd 100644 --- a/src/common/call.c +++ b/src/common/call.c @@ -35,6 +35,23 @@ #define DISC_TIMEOUT 30 +//#define DEBUG_LEVEL + +#ifdef DEBUG_LEVEL +static double level_of(double *samples, int count) +{ + double level = 0; + int i; + + for (i = 0; i < count; i++) { + if (samples[i] > level) + level = samples[i]; + } + + return level; +} +#endif + /* stream patterns/announcements */ int16_t *test_spl = NULL; int16_t *ringback_spl = NULL; @@ -221,7 +238,7 @@ static void get_test_patterns(int16_t *samples, int length) if (pos >= size) *samples++ = 0; else - *samples++ = spl[pos] >> 1; + *samples++ = spl[pos] >> 2; if (++pos == max) pos = 0; } @@ -477,7 +494,8 @@ 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, 0.0, samplerate, 3700.0, 0.0); + /* use +3.17 dBm0 (factor 1.44) for complete range of sound card */ + call.sound = sound_open(audiodev, NULL, NULL, 1, 0.0, samplerate, 1.44, 4000.0); if (!call.sound) { PDEBUG(DSENDER, DEBUG_ERROR, "No sound device!\n"); @@ -677,7 +695,6 @@ void process_call(int c) default: jitter_load(&call.dejitter, samples, count); } - samples_to_int16(spl, samples, count); samples_list[0] = samples; rc = sound_write(call.sound, samples_list, count, NULL, NULL, 1); if (rc < 0) { @@ -904,8 +921,6 @@ void call_in_release(int callref, int cause) /* forward audio to MNCC or call instance */ void call_tx_audio(int callref, sample_t *samples, int count) { - int16_t spl[count]; - if (!callref) return; @@ -920,6 +935,10 @@ void call_tx_audio(int callref, sample_t *samples, int count) /* forward audio */ data->msg_type = ANALOG_8000HZ; data->callref = callref; +#ifdef DEBUG_LEVEL + double lev = level_of(samples, count); + printf(" mobil-level: %s%.4f\n", debug_db(lev), (20 * log10(lev))); +#endif samples_to_int16((int16_t *)data->data, samples, count); mncc_write(buf, sizeof(buf)); @@ -934,6 +953,7 @@ void call_tx_audio(int callref, sample_t *samples, int count) } else /* else, if no sound is used, send test tone to mobile */ if (call.state == CALL_CONNECT) { + int16_t spl[count]; get_test_patterns(spl, count); int16_to_samples(samples, spl, count); call_rx_audio(callref, samples, count); @@ -953,6 +973,13 @@ void call_mncc_clock(void) data->callref = process->callref; /* try to get patterns, else copy the samples we got */ get_process_patterns(process, (int16_t *)data->data, 160); +#ifdef DEBUG_LEVEL + sample_t samples[160]; + int16_to_samples(samples, (int16_t *)data->data, 160); + double lev = level_of(samples, 160); + printf(" mobil-level: %s%.4f\n", debug_db(lev), (20 * log10(lev))); + samples_to_int16((int16_t *)data->data, samples, 160); +#endif mncc_write(buf, sizeof(buf)); } process = process->next; @@ -978,6 +1005,10 @@ void call_mncc_recv(uint8_t *buf, int length) if (is_process_pattern(data->callref)) return; int16_to_samples(samples, (int16_t *)data->data, count); +#ifdef DEBUG_LEVEL + double lev = level_of(samples, count); + printf("festnetz-level: %s %.4f\n", debug_db(lev), (20 * log10(lev))); +#endif call_rx_audio(data->callref, samples, count); return; } diff --git a/src/common/compandor.c b/src/common/compandor.c index 8db2f87..d7c7bce 100644 --- a/src/common/compandor.c +++ b/src/common/compandor.c @@ -35,6 +35,9 @@ /* Minimum level value to keep state */ #define ENVELOPE_MIN 0.001 +/* Maximum level, to prevent sqrt_tab to overflow */ +#define ENVELOPE_MAX 9.990 + static double sqrt_tab[10000]; /* @@ -43,7 +46,7 @@ static double sqrt_tab[10000]; * Hopefully this is correct * */ -void init_compandor(compandor_t *state, int samplerate, double attack_ms, double recovery_ms, int unaffected_level) +void init_compandor(compandor_t *state, int samplerate, double attack_ms, double recovery_ms, double unaffected_level) { int i; @@ -95,6 +98,8 @@ void compress_audio(compandor_t *state, sample_t *samples, int num) envelope = peak; if (envelope < ENVELOPE_MIN) envelope = ENVELOPE_MIN; + if (envelope > ENVELOPE_MAX) + envelope = ENVELOPE_MAX; value = value / sqrt_tab[(int)(envelope / 0.001)]; //if (i > 47000.0 && i < 48144) diff --git a/src/common/compandor.h b/src/common/compandor.h index 1d027dd..2151baa 100644 --- a/src/common/compandor.h +++ b/src/common/compandor.h @@ -15,7 +15,7 @@ typedef struct compandor { } e; } compandor_t; -void init_compandor(compandor_t *state, int samplerate, double attack_ms, double recovery_ms, int unaffected_level); +void init_compandor(compandor_t *state, int samplerate, double attack_ms, double recovery_ms, double unaffected_level); void compress_audio(compandor_t *state, sample_t *samples, int num); void expand_audio(compandor_t *state, sample_t *samples, int num); diff --git a/src/common/display.h b/src/common/display.h index 7b1c2e9..8590298 100644 --- a/src/common/display.h +++ b/src/common/display.h @@ -23,7 +23,7 @@ void get_win_size(int *w, int *h); void display_wave_init(sender_t *sender, int samplerate); void display_wave_on(int on); void display_wave_limit_scroll(int on); -void display_wave(sender_t *sender, sample_t *samples, int length); +void display_wave(sender_t *sender, sample_t *samples, int length, double range); void display_iq_init(int samplerate); void display_iq_on(int on); diff --git a/src/common/display_wave.c b/src/common/display_wave.c index 38a74c7..9aea886 100644 --- a/src/common/display_wave.c +++ b/src/common/display_wave.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include "sample.h" #include "sender.h" @@ -110,10 +111,10 @@ void display_wave_limit_scroll(int on) * HEIGHT is odd, so the center line's char is '-' (otherwise '_') * (HEIGHT - 1) / 2 = 1, so the center line is drawn in line 1 * - * y is in range of 0..5, so these are 5 steps, where 2 to 2.999 is the + * y is in range of 0..4, so these are 5 steps, where 2 is the * center line. this is calculated by (HEIGHT * 2 - 1) */ -void display_wave(sender_t *sender, sample_t *samples, int length) +void display_wave(sender_t *sender, sample_t *samples, int length, double range) { dispwav_t *disp = &sender->dispwav; int pos, max; @@ -147,9 +148,16 @@ void display_wave(sender_t *sender, sample_t *samples, int length) if (pos == width) { memset(&screen, ' ', sizeof(screen)); for (j = 0; j < width; j++) { - y = (32767 - (int32_t)buffer[j]) * (HEIGHT * 2 - 1) / 65536; + /* Input value is scaled to range -1 .. 1 and then substracted from 1, + * so the result ranges from 0 .. 2. + * HEIGHT-1 is multiplied with the range, so a HEIGHT of 3 would allow + * 0..4 (5 steps) and a HEIGHT of 11 would allow 0..20 (21 steps). + * We always use odd number of steps, so there will be a center between + * values. + */ + y = round((1.0 - buffer[j] / range) * (double)(HEIGHT - 1)); /* only display level, if it is in range */ - if (y >= 0 && y < HEIGHT * 2) + if (y >= 0 && y < HEIGHT * 2 - 1) screen[y >> 1][j] = (y & 1) ? '_' : '-'; } sprintf(screen[0], "(chan %d", sender->kanal); diff --git a/src/common/dtmf.c b/src/common/dtmf.c index b9870a1..f3d3283 100644 --- a/src/common/dtmf.c +++ b/src/common/dtmf.c @@ -25,10 +25,12 @@ #define PI M_PI -#define TX_PEAK_DTMF 7000 /* single dtmf tone peak (note this is half to total peak) */ -#define DTMF_DURATION 0.100 /* duration in seconds */ +static double tx_peak_dtmf_low = 0.2818 / SPEECH_LEVEL; /* -11 dBm, relative to speech level */ +static double tx_peak_dtmf_high = 0.3548 / SPEECH_LEVEL;/* -9 dBm, relative to speech level */ +#define DTMF_DURATION 0.100 /* duration in seconds */ -static double dsp_sine_dtmf[256]; +static sample_t dsp_sine_dtmf_low[65536]; +static sample_t dsp_sine_dtmf_high[65536]; void dtmf_init(dtmf_t *dtmf, int samplerate) { @@ -39,8 +41,10 @@ void dtmf_init(dtmf_t *dtmf, int samplerate) dtmf->max = (int)((double)samplerate * DTMF_DURATION + 0.5); // FIXME: do this globally and not per instance */ - for (i = 0; i < 256; i++) - dsp_sine_dtmf[i] = (int)(sin((double)i / 256.0 * 2.0 * PI) * TX_PEAK_DTMF); + for (i = 0; i < 65536; i++) { + dsp_sine_dtmf_low[i] = sin((double)i / 65536.0 * 2.0 * PI) * tx_peak_dtmf_low; + dsp_sine_dtmf_high[i] = sin((double)i / 65536.0 * 2.0 * PI) * tx_peak_dtmf_high; + } } /* set dtmf tone */ @@ -71,8 +75,8 @@ void dtmf_set_tone(dtmf_t *dtmf, char tone) } dtmf->tone = tone; dtmf->pos = 0; - dtmf->phaseshift256[0] = 256.0 / ((double)dtmf->samplerate / f1); - dtmf->phaseshift256[1] = 256.0 / ((double)dtmf->samplerate / f2); + dtmf->phaseshift65536[0] = 65536.0 / ((double)dtmf->samplerate / f1); + dtmf->phaseshift65536[1] = 65536.0 / ((double)dtmf->samplerate / f2); } /* Generate audio stream from DTMF tone. Keep phase for next call of function. */ @@ -87,20 +91,20 @@ void dtmf_tone(dtmf_t *dtmf, sample_t *samples, int length) return; } - phaseshift = dtmf->phaseshift256; - phase = dtmf->phase256; + phaseshift = dtmf->phaseshift65536; + phase = dtmf->phase65536; pos = dtmf->pos; max = dtmf->max; for (i = 0; i < length; i++) { - *samples++ = dsp_sine_dtmf[((uint8_t)phase[0]) & 0xff] - + dsp_sine_dtmf[((uint8_t)phase[1]) & 0xff]; + *samples++ = dsp_sine_dtmf_low[(uint16_t)phase[0]] + + dsp_sine_dtmf_high[(uint16_t)phase[1]]; phase[0] += phaseshift[0]; - if (phase[0] >= 256) - phase[0] -= 256; + if (phase[0] >= 65536) + phase[0] -= 65536; phase[1] += phaseshift[1]; - if (phase[1] >= 256) - phase[1] -= 256; + if (phase[1] >= 65536) + phase[1] -= 65536; /* tone ends */ if (++pos == max) { diff --git a/src/common/dtmf.h b/src/common/dtmf.h index 477affd..d6a5322 100644 --- a/src/common/dtmf.h +++ b/src/common/dtmf.h @@ -4,8 +4,8 @@ typedef struct dtmf { char tone; /* current tone to be played */ int pos; /* sample counter for tone */ int max; /* max number of samples for tone duration */ - double phaseshift256[2]; /* how much the phase of sine wave changes per sample */ - double phase256[2]; /* current phase */ + double phaseshift65536[2]; /* how much the phase of sine wave changes per sample */ + double phase65536[2]; /* current phase */ } dtmf_t; void dtmf_init(dtmf_t *dtmf, int samplerate); diff --git a/src/common/emphasis.c b/src/common/emphasis.c index 524c37b..3fb6679 100644 --- a/src/common/emphasis.c +++ b/src/common/emphasis.c @@ -21,6 +21,7 @@ #include #include #include +#include "sample.h" #include "filter.h" #include "emphasis.h" #include "debug.h" @@ -29,7 +30,7 @@ #define CUT_OFF_H 100.0 /* cut-off frequency for high-pass filter */ -static void gen_sine(double *samples, int num, int samplerate, double freq) +static void gen_sine(sample_t *samples, int num, int samplerate, double freq) { int i; @@ -37,7 +38,7 @@ static void gen_sine(double *samples, int num, int samplerate, double freq) samples[i] = cos(2.0 * M_PI * freq / (double)samplerate * (double)i); } -static double get_level(double *samples, int num) +static double get_level(sample_t *samples, int num) { int i; double envelope = 0; @@ -52,7 +53,7 @@ static double get_level(double *samples, int num) int init_emphasis(emphasis_t *state, int samplerate, double cut_off) { double factor; - double test_samples[samplerate / 10]; + sample_t test_samples[samplerate / 10]; memset(state, 0, sizeof(*state)); @@ -78,7 +79,7 @@ int init_emphasis(emphasis_t *state, int samplerate, double cut_off) return 0; } -void pre_emphasis(emphasis_t *state, double *samples, int num) +void pre_emphasis(emphasis_t *state, sample_t *samples, int num) { double x, y, x_last, factor, amp; int i; @@ -101,7 +102,7 @@ void pre_emphasis(emphasis_t *state, double *samples, int num) state->p.x_last = x_last; } -void de_emphasis(emphasis_t *state, double *samples, int num) +void de_emphasis(emphasis_t *state, sample_t *samples, int num) { double x, y, y_last, factor, amp; int i; @@ -125,7 +126,7 @@ void de_emphasis(emphasis_t *state, double *samples, int num) } /* high pass filter to remove DC and low frequencies */ -void dc_filter(emphasis_t *state, double *samples, int num) +void dc_filter(emphasis_t *state, sample_t *samples, int num) { filter_process(&state->d.hp, samples, num); } diff --git a/src/common/emphasis.h b/src/common/emphasis.h index f14afd1..283afb1 100644 --- a/src/common/emphasis.h +++ b/src/common/emphasis.h @@ -15,7 +15,7 @@ typedef struct emphasis { #define CUT_OFF_EMPHASIS_DEFAULT 300.0 int init_emphasis(emphasis_t *state, int samplerate, double cut_off); -void pre_emphasis(emphasis_t *state, double *samples, int num); -void de_emphasis(emphasis_t *state, double *samples, int num); -void dc_filter(emphasis_t *state, double *samples, int num); +void pre_emphasis(emphasis_t *state, sample_t *samples, int num); +void de_emphasis(emphasis_t *state, sample_t *samples, int num); +void dc_filter(emphasis_t *state, sample_t *samples, int num); diff --git a/src/common/filter.c b/src/common/filter.c index 3aea327..0a5c0dd 100644 --- a/src/common/filter.c +++ b/src/common/filter.c @@ -22,6 +22,7 @@ #include #include #include +#include "sample.h" #include "filter.h" #define PI M_PI @@ -65,7 +66,7 @@ void filter_highpass_init(filter_t *bq, double frequency, int samplerate, int it bq->b2 = (1 - K / Q + K * K) * norm; } -void filter_process(filter_t *bq, double *samples, int length) +void filter_process(filter_t *bq, sample_t *samples, int length) { double a0, a1, a2, b1, b2; double *z1, *z2; diff --git a/src/common/filter.h b/src/common/filter.h index 42f051b..9f33fe2 100644 --- a/src/common/filter.h +++ b/src/common/filter.h @@ -9,6 +9,6 @@ typedef struct filter { void filter_lowpass_init(filter_t *bq, double frequency, int samplerate, int iterations); void filter_highpass_init(filter_t *bq, double frequency, int samplerate, int iterations); -void filter_process(filter_t *bq, double *samples, int length); +void filter_process(filter_t *bq, sample_t *samples, int length); #endif /* _FILTER_H */ diff --git a/src/common/sample.c b/src/common/sample.c index 107c8e0..72ba941 100644 --- a/src/common/sample.c +++ b/src/common/sample.c @@ -1,27 +1,64 @@ +/* Sample definition + * + * (C) 2017 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 "sample.h" +#include "sample.h" + +/* + * A regular voice conversation takes place at this factor below the full range + * of 16 bits signed value: + */ +static double int_16_speech_level = SPEECH_LEVEL * 0.7079; /* 16 dBm below dBm0, which is about 3dBm below full 16 bit range */ + +/* A sample_t is a value that has virtually infinite precision but will also + * support high numbers. 'double' or 'float' types are sufficient. + * + * When using sample_t inside signal processing of each base station, the + * level of +- 1 is relative to the normal speach evenlope. + * + * When converting sample_t to int16_t, the level of +- 1 is reduced by factor. + * This way the speech may be louder before clipping happens. + * + * When using sample_t to modulate (SDR or sound card), the level is changed, + * so it represents the frequency deviation in Hz. The deviation of speech + * envelope is network dependant. + */ void samples_to_int16(int16_t *spl, sample_t *samples, int length) { + int32_t value; + while (length--) { - if (*samples > 32767.0) - *spl = 32767; - else if (*samples < -32767.0) - *spl = -32767; + value = *samples++ * int_16_speech_level * 32768.0; + if (value > 32767.0) + *spl++ = 32767; + else if (value < -32767.0) + *spl++ = -32767; else - *spl = (uint16_t)(*samples); - samples++; - spl++; + *spl++ = (uint16_t)value; } } void int16_to_samples(sample_t *samples, int16_t *spl, int length) { while (length--) { - *samples = (double)(*spl); - samples++; - spl++; + *samples++ = (double)(*spl++) / 32767.0 / int_16_speech_level; } } diff --git a/src/common/sample.h b/src/common/sample.h index fb578eb..01a17df 100644 --- a/src/common/sample.h +++ b/src/common/sample.h @@ -1,6 +1,8 @@ typedef double sample_t; +#define SPEECH_LEVEL 0.1585 + void samples_to_int16(int16_t *spl, sample_t *samples, int length); void int16_to_samples(sample_t *samples, int16_t *spl, int length); diff --git a/src/common/samplerate.c b/src/common/samplerate.c index 18e039e..66b763f 100644 --- a/src/common/samplerate.c +++ b/src/common/samplerate.c @@ -124,7 +124,7 @@ int samplerate_upsample(samplerate_t *state, sample_t *input, int input_num, sam if (input == output) { /* copy samples */ - for (i = 0; i < input_num; i++) + for (i = 0; i < output_num; i++) *output++ = samples[i]; } diff --git a/src/common/sdr.c b/src/common/sdr.c index 77b31a6..dd956b0 100644 --- a/src/common/sdr.c +++ b/src/common/sdr.c @@ -47,7 +47,6 @@ typedef struct sdr { 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 */ double amplitude; /* amplitude of each carrier */ @@ -84,15 +83,19 @@ int sdr_init(const char *device_args, double rx_gain, double tx_gain, const char return 0; } -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) +void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double max_deviation, double max_modulation) { sdr_t *sdr; + double bandwidth; double tx_center_frequency, rx_center_frequency; int rc; int c; display_iq_init(samplerate); + bandwidth = 2.0 * (max_deviation + max_modulation); + PDEBUG(DSDR, DEBUG_INFO, "Using Bandwidth of 2 * (%.1f + %.1f) = %.1f\n", max_deviation / 1000, max_modulation / 1000, bandwidth / 1000); + if (channels < 1) { PDEBUG(DSDR, DEBUG_ERROR, "No channel given, please fix!\n"); abort(); @@ -105,7 +108,6 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq } sdr->channels = channels; sdr->samplerate = samplerate; - sdr->spl_deviation = sample_deviation; sdr->amplitude = 0.4 / (double)channels; // FIXME: actual amplitude 0.1? /* special case where we use a paging frequency */ @@ -124,8 +126,8 @@ 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]; - filter_lowpass_init(&sdr->chan[c].rx_lp[0], bandwidth, samplerate, 1); - filter_lowpass_init(&sdr->chan[c].rx_lp[1], bandwidth, samplerate, 1); + filter_lowpass_init(&sdr->chan[c].rx_lp[0], bandwidth / 2.0, samplerate, 1); + filter_lowpass_init(&sdr->chan[c].rx_lp[1], bandwidth / 2.0, samplerate, 1); } if (sdr->paging_channel) { PDEBUG(DSDR, DEBUG_INFO, "Paging Frequency: TX = %.6f MHz\n", paging_frequency / 1e6); @@ -190,21 +192,21 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq PDEBUG(DSDR, DEBUG_INFO, "Using gain: TX %.1f dB, RX %.1f dB\n", sdr_tx_gain, sdr_rx_gain); if (sdr_write_iq_rx_wave) { - rc = wave_create_record(&sdr->wave_rx_rec, sdr_write_iq_rx_wave, sdr->samplerate, 2); + rc = wave_create_record(&sdr->wave_rx_rec, sdr_write_iq_rx_wave, sdr->samplerate, 2, 1.0); if (rc < 0) { PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n"); goto error; } } if (sdr_write_iq_tx_wave) { - rc = wave_create_record(&sdr->wave_tx_rec, sdr_write_iq_tx_wave, sdr->samplerate, 2); + rc = wave_create_record(&sdr->wave_tx_rec, sdr_write_iq_tx_wave, sdr->samplerate, 2, 1.0); if (rc < 0) { PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n"); goto error; } } if (sdr_read_iq_rx_wave) { - rc = wave_create_playback(&sdr->wave_rx_play, sdr_read_iq_rx_wave, sdr->samplerate, 2); + rc = wave_create_playback(&sdr->wave_rx_play, sdr_read_iq_rx_wave, sdr->samplerate, 2, 1.0); if (rc < 0) { PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE playback instance!\n"); goto error; @@ -269,7 +271,7 @@ int sdr_write(void *inst, sample_t **samples, int num, enum paging_signal __attr /* modulate */ for (s = 0, ss = 0; s < num; s++) { /* deviation is defined by the sample value and the offset */ - dev = offset + (double)samples[c][s] * sdr->spl_deviation; + dev = offset + samples[c][s]; #ifdef FAST_SINE phase += 256.0 * dev / rate; if (phase < 0.0) @@ -294,20 +296,8 @@ int sdr_write(void *inst, sample_t **samples, int num, enum paging_signal __attr if (sdr->wave_tx_rec.fp) { sample_t spl[2][num], *spl_list[2] = { spl[0], spl[1] }; for (s = 0, ss = 0; s < num; s++) { - if (buff[ss] >= 1.0) - spl[0][s] = 32767.0; - else if (buff[ss] <= -1.0) - spl[0][s] = -32767.0; - else - spl[0][s] = 32767.0 * buff[ss]; - ss++; - if (buff[ss] >= 1.0) - spl[1][s] = 32767.0; - else if (buff[ss] <= -1.0) - spl[1][s] = -32767.0; - else - spl[1][s] = 32767.0 * buff[ss]; - ss++; + spl[0][s] = buff[ss++]; + spl[1][s] = buff[ss++]; } wave_write(&sdr->wave_tx_rec, spl_list, num); } @@ -325,7 +315,7 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels) { sdr_t *sdr = (sdr_t *)inst; float buff[num * 2]; - double I[num], Q[num], i, q; + sample_t I[num], Q[num], i, q; int count; int c, s, ss; double phase, rot, last_phase, dev, rate; @@ -341,20 +331,8 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels) if (sdr->wave_rx_rec.fp) { sample_t spl[2][count], *spl_list[2] = { spl[0], spl[1] }; for (s = 0, ss = 0; s < count; s++) { - if (buff[ss] >= 1.0) - spl[0][s] = 32767.0; - else if (buff[ss] <= -1.0) - spl[0][s] = -32767.0; - else - spl[0][s] = 32767.0 * buff[ss]; - ss++; - if (buff[ss] >= 1.0) - spl[1][s] = 32767.0; - else if (buff[ss] <= -1.0) - spl[1][s] = -32767.0; - else - spl[1][s] = 32767.0 * buff[ss]; - ss++; + spl[0][s] = buff[ss++]; + spl[1][s] = buff[ss++]; } wave_write(&sdr->wave_rx_rec, spl_list, count); } @@ -362,8 +340,8 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels) sample_t spl[2][count], *spl_list[2] = { spl[0], spl[1] }; wave_read(&sdr->wave_rx_play, spl_list, count); for (s = 0, ss = 0; s < count; s++) { - buff[ss++] = spl[0][s] / 32767.0; - buff[ss++] = spl[1][s] / 32767.0; + buff[ss++] = spl[0][s]; + buff[ss++] = spl[1][s]; } } display_iq(buff, count); @@ -391,7 +369,7 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels) else if (dev > 0.49) dev -= 1.0; dev *= rate; - samples[c][s] = dev / sdr->spl_deviation; + samples[c][s] = dev; } sdr->chan[c].rx_last_phase = last_phase; } diff --git a/src/common/sender.c b/src/common/sender.c index 62eec06..f59ad94 100644 --- a/src/common/sender.c +++ b/src/common/sender.c @@ -41,8 +41,6 @@ int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empf sender->kanal = kanal; sender->sendefrequenz = sendefrequenz; sender->empfangsfrequenz = empfangsfrequenz; - sender->bandwidth = 4000; /* default is overwritten by dsp.c */ - sender->sample_deviation = 0.2; /* default is overwritten by dsp.c */ strncpy(sender->audiodev, audiodev, sizeof(sender->audiodev) - 1); sender->samplerate = samplerate; sender->rx_gain = rx_gain; @@ -168,21 +166,21 @@ int sender_open_audio(void) } if (master->write_rx_wave) { - rc = wave_create_record(&master->wave_rx_rec, master->write_rx_wave, master->samplerate, channels); + rc = wave_create_record(&master->wave_rx_rec, master->write_rx_wave, master->samplerate, channels, master->max_deviation); if (rc < 0) { PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n"); return rc; } } if (master->write_tx_wave) { - rc = wave_create_record(&master->wave_tx_rec, master->write_tx_wave, master->samplerate, channels); + rc = wave_create_record(&master->wave_tx_rec, master->write_tx_wave, master->samplerate, channels, master->max_deviation); if (rc < 0) { PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE recoding instance!\n"); return rc; } } if (master->read_rx_wave) { - rc = wave_create_playback(&master->wave_rx_play, master->read_rx_wave, master->samplerate, channels); + rc = wave_create_playback(&master->wave_rx_play, master->read_rx_wave, master->samplerate, channels, master->max_deviation); if (rc < 0) { PDEBUG(DSENDER, DEBUG_ERROR, "Failed to create WAVE playback instance!\n"); return rc; @@ -190,7 +188,7 @@ int sender_open_audio(void) } /* open device */ - master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, paging_frequency, master->samplerate, master->bandwidth, master->sample_deviation); + master->audio = master->audio_open(master->audiodev, tx_f, rx_f, channels, paging_frequency, master->samplerate, master->max_deviation, master->max_modulation); if (!master->audio) { PDEBUG(DSENDER, DEBUG_ERROR, "No audio device!\n"); return -EIO; @@ -225,6 +223,17 @@ void sender_destroy(sender_t *sender) jitter_destroy(&sender->dejitter); } +void sender_set_fm(sender_t *sender, double max_deviation, double max_modulation, double dBm0_deviation, double max_display) +{ + sender->max_deviation = max_deviation; + sender->max_modulation = max_modulation; + sender->dBm0_deviation = dBm0_deviation; + sender->max_display = max_display; + + PDEBUG_CHAN(DSENDER, DEBUG_DEBUG, "Maxium deviation: %.1f kHz, Maximum modulation: %.1f kHz\n", max_deviation / 1000.0, max_modulation / 1000.0); + PDEBUG_CHAN(DSENDER, DEBUG_DEBUG, "Deviation at dBm0 (audio level): %.1f kHz\n", dBm0_deviation / 1000.0); +} + static void gain_samples(sample_t *samples, int length, double gain) { int i; @@ -278,12 +287,14 @@ cant_recover: sender_send(inst, samples[i], count); /* internal loopback: loop back TX audio to RX */ if (inst->loopback == 1) { - display_wave(inst, samples[i], count); + display_wave(inst, samples[i], count, inst->max_display); sender_receive(inst, samples[i], count); } /* do pre emphasis towards radio */ if (inst->pre_emphasis) pre_emphasis(&inst->estate, samples[i], count); + /* normal level to frequency deviation of dBm0 */ + gain_samples(samples[i], count, inst->dBm0_deviation); /* set paging signal */ paging_signal[i] = inst->paging_signal; on[i] = inst->paging_on; @@ -328,6 +339,8 @@ transmit_later: /* loop through all channels */ for (i = 0, inst = sender; inst; i++, inst = inst->slave) { + /* frequency deviation of dBm0 to normal level */ + gain_samples(samples[i], count, 1.0 / inst->dBm0_deviation); /* rx gain */ if (inst->rx_gain != 1.0) gain_samples(samples[i], count, inst->rx_gain); @@ -337,7 +350,7 @@ transmit_later: de_emphasis(&inst->estate, samples[i], count); } if (inst->loopback != 1) { - display_wave(inst, samples[i], count); + display_wave(inst, samples[i], count, inst->max_display); sender_receive(inst, samples[i], count); } if (inst->loopback == 3) diff --git a/src/common/sender.h b/src/common/sender.h index 1af6be1..cb59671 100644 --- a/src/common/sender.h +++ b/src/common/sender.h @@ -31,8 +31,12 @@ typedef struct sender { 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) */ + + /* fm levels */ + double max_deviation; /* max frequency deviation */ + double max_modulation; /* max frequency modulated */ + double dBm0_deviation; /* deviation of 1000 Hz reference tone at dBm0 */ + double max_display; /* level of displaying wave form */ /* audio */ void *audio; @@ -85,6 +89,7 @@ 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 paging_signal paging_signal); void sender_destroy(sender_t *sender); +void sender_set_fm(sender_t *sender, double max_deviation, double max_modulation, double dBm0_deviation, double max_display); int sender_open_audio(void); void process_sender_audio(sender_t *sender, int *quit, int latspl); void sender_send(sender_t *sender, sample_t *samples, int count); diff --git a/src/common/sound_alsa.c b/src/common/sound_alsa.c index efc93de..c12fe25 100644 --- a/src/common/sound_alsa.c +++ b/src/common/sound_alsa.c @@ -27,6 +27,7 @@ typedef struct sound { snd_pcm_t *phandle, *chandle; int pchannels, cchannels; + double spl_deviation; /* how much deviation is one sample step */ double paging_phaseshift; /* phase to shift every sample */ double paging_phase; /* current phase */ } sound_t; @@ -131,7 +132,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, double __attribute__((unused)) paging_frequency, 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 max_deviation, double __attribute__((unused)) max_modulation) { sound_t *sound; int rc; @@ -147,6 +148,7 @@ void *sound_open(const char *audiodev, double __attribute__((unused)) *tx_freque return NULL; } + sound->spl_deviation = max_deviation / 32767.0; sound->paging_phaseshift = 1.0 / ((double)samplerate / 1000.0); rc = snd_pcm_open(&sound->phandle, audiodev, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); @@ -252,6 +254,7 @@ static void gen_paging_tone(sound_t *sound, int16_t *samples, int length, enum p int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *paging_signal, int *on, int channels) { sound_t *sound = (sound_t *)inst; + double spl_deviation = sound->spl_deviation; int32_t value; int16_t buff[num << 1]; int rc; @@ -263,7 +266,7 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag int16_t paging[num << 1]; gen_paging_tone(sound, paging, num, paging_signal[0], on[0]); for (i = 0, ii = 0; i < num; i++) { - value = samples[0][i]; + value = samples[0][i] / spl_deviation; if (value > 32767) value = 32767; else if (value < -32767) @@ -273,13 +276,13 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag } } else if (channels == 2) { for (i = 0, ii = 0; i < num; i++) { - value = samples[0][i]; + value = samples[0][i] / spl_deviation; if (value > 32767) value = 32767; else if (value < -32767) value = -32767; buff[ii++] = value; - value = samples[1][i]; + value = samples[1][i] / spl_deviation; if (value > 32767) value = 32767; else if (value < -32767) @@ -288,7 +291,7 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag } } else { for (i = 0, ii = 0; i < num; i++) { - value = samples[0][i]; + value = samples[0][i] / spl_deviation; if (value > 32767) value = 32767; else if (value < -32767) @@ -300,7 +303,7 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag } else { /* one channel */ for (i = 0, ii = 0; i < num; i++) { - value = samples[0][i]; + value = samples[0][i] / spl_deviation; if (value > 32767) value = 32767; else if (value < -32767) @@ -328,6 +331,7 @@ int sound_write(void *inst, sample_t **samples, int num, enum paging_signal *pag int sound_read(void *inst, sample_t **samples, int num, int channels) { sound_t *sound = (sound_t *)inst; + double spl_deviation = sound->spl_deviation; int16_t buff[num << 1]; int32_t spl; int in, rc; @@ -361,17 +365,17 @@ int sound_read(void *inst, sample_t **samples, int num, int channels) for (i = 0, ii = 0; i < rc; i++) { spl = buff[ii++]; spl += buff[ii++]; - samples[0][i] = (sample_t)spl; + samples[0][i] = (double)spl * spl_deviation; } } else { for (i = 0, ii = 0; i < rc; i++) { - samples[0][i] = (sample_t)buff[ii++]; - samples[1][i] = (sample_t)buff[ii++]; + samples[0][i] = (double)buff[ii++] * spl_deviation; + samples[1][i] = (double)buff[ii++] * spl_deviation; } } } else { for (i = 0, ii = 0; i < rc; i++) { - samples[0][i] = (sample_t)buff[ii++]; + samples[0][i] = (double)buff[ii++] * spl_deviation; } } diff --git a/src/common/wave.c b/src/common/wave.c index 804fd5a..c2f2462 100644 --- a/src/common/wave.c +++ b/src/common/wave.c @@ -34,7 +34,7 @@ struct fmt { uint16_t bits_sample; /* bits per sample (one channel) */ }; -int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels) +int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels, double max_deviation) { /* RIFFxxxxWAVEfmt xxxx(fmt size)dataxxxx... */ char dummyheader[4 + 4 + 4 + 4 + 4 + sizeof(struct fmt) + 4 + 4]; @@ -43,6 +43,7 @@ int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, in memset(rec, 0, sizeof(*rec)); rec->samplerate = samplerate; rec->channels = channels; + rec->max_deviation = max_deviation; rec->fp = fopen(filename, "w"); if (!rec->fp) { @@ -58,7 +59,7 @@ int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, in return 0; } -int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels) +int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels, double max_deviation) { uint8_t buffer[256]; struct fmt fmt; @@ -68,6 +69,7 @@ int wave_create_playback(wave_play_t *play, const char *filename, int samplerate memset(play, 0, sizeof(*play)); play->channels = channels; + play->max_deviation = max_deviation; play->fp = fopen(filename, "r"); if (!play->fp) { @@ -196,6 +198,8 @@ error: int wave_read(wave_play_t *play, sample_t **samples, int length) { + double max_deviation = play->max_deviation; + int16_t value; /* must be int16, so assembling bytes work */ uint8_t buff[2 * length * play->channels]; int __attribute__((__unused__)) len; int i, j, c; @@ -212,11 +216,12 @@ int wave_read(wave_play_t *play, sample_t **samples, int length) if (!play->left) printf("*** Finished reading WAVE file.\n"); - /* read and correct endiness */ + /* read and correct endianness */ len = fread(buff, 1, 2 * length * play->channels, play->fp); for (i = 0, j = 0; i < length; i++) { for (c = 0; c < play->channels; c++) { - samples[c][i] = (double)(buff[j] + (buff[j + 1] << 8)); + value = buff[j] + (buff[j + 1] << 8); + samples[c][i] = (double)value / 32767.0 * max_deviation; j += 2; } } @@ -226,15 +231,16 @@ int wave_read(wave_play_t *play, sample_t **samples, int length) int wave_write(wave_rec_t *rec, sample_t **samples, int length) { + double max_deviation = rec->max_deviation; int32_t value; uint8_t buff[2 * length * rec->channels]; int __attribute__((__unused__)) len; int i, j, c; - /* write and correct endiness */ + /* write and correct endianness */ for (i = 0, j = 0; i < length; i++) { for (c = 0; c < rec->channels; c++) { - value = samples[c][i]; + value = samples[c][i] / max_deviation * 32767.0; if (value > 32767) value = 32767; else if (value < -32767) diff --git a/src/common/wave.h b/src/common/wave.h index 59c1db8..54c20fb 100644 --- a/src/common/wave.h +++ b/src/common/wave.h @@ -2,6 +2,7 @@ typedef struct wave_rec { FILE *fp; int channels; + double max_deviation; int samplerate; uint32_t written; /* how much samples written */ } wave_rec_t; @@ -9,11 +10,12 @@ typedef struct wave_rec { typedef struct wave_play { FILE *fp; int channels; + double max_deviation; uint32_t left; /* how much samples left */ } wave_play_t; -int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels); -int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels); +int wave_create_record(wave_rec_t *rec, const char *filename, int samplerate, int channels, double max_deviation); +int wave_create_playback(wave_play_t *play, const char *filename, int samplerate, int channels, double max_deviation); int wave_read(wave_play_t *play, sample_t **samples, int length); int wave_write(wave_rec_t *rec, sample_t **samples, int length); void wave_destroy_record(wave_rec_t *rec); diff --git a/src/nmt/dsp.c b/src/nmt/dsp.c index 7fb8fe5..3d7dd52 100644 --- a/src/nmt/dsp.c +++ b/src/nmt/dsp.c @@ -34,23 +34,36 @@ #define PI M_PI -/* Notes on frequency deviation of supervidory signal: +/* Notes on TX_PEAK_FSK level: * - * The FSK deviation at 1500 Hz is 3.5 KHz. If we use a level of 10000 - * The supervisory deviation shall be 0.3 KHz: 10000 / 3.5 * 0.3 = 857 - * Supervisory is raised by pre-emphasis by factor 2.68 (4015 / 1500), - * so we need to lower it: 857 / 2.68 = 320 + * This deviation is -2.2db below the dBm0 deviation. + * + * At 1800 Hz the deviation shall be 4.2 kHz, so with emphasis the deviation + * at 1000 Hz would be theoretically 2.333 kHz. This is factor 0.777 below + * 3 kHz deviation we want at dBm0. + */ + +/* Notes on TX_PEAK_SUPER (supervisory signal) level: + * + * This level has 0.3 kHz deviation at 4015 Hz. + * + * Same calculation as above, but now we want 0.3 kHz deviation after emphasis, + * so we calculate what we would need at 1000 Hz in relation to 3 kHz + * deviation. */ /* signaling */ -#define BANDWIDTH 6000.0 /* maximum bandwidth FIXME */ -#define COMPANDOR_0DB 32767 /* works quite well */ -#define TX_PEAK_FSK 10000.0 /* peak amplitude of signaling FSK +-3.5 KHz @ 1500 Hz */ -#define TX_PEAK_SUPER (TX_PEAK_FSK / 3.5 * 0.3 / 2.68) /* peak amplitude of supervisory signal +-0.3 KHz @ 4015 Hz */ +#define MAX_DEVIATION 4700.0 +#define MAX_MODULATION 4055.0 +#define DBM0_DEVIATION 3000.0 /* deviation of dBm0 at 1 kHz */ +#define COMPANDOR_0DB 1.0 /* A level of 0dBm (1.0) shall be unaccected */ +#define TX_PEAK_FSK (4200.0 / 1800.0 * 1000.0 / DBM0_DEVIATION) +#define TX_PEAK_SUPER (300.0 / 4015.0 * 1000.0 / DBM0_DEVIATION) +#define MAX_DISPLAY 1.4 /* something above dBm0 */ #define BIT_RATE 1200 /* baud rate */ -#define STEPS_PER_BIT 10 /* step every 1/12000 sec */ +#define FILTER_STEPS 0.1 /* step every 1/12000 sec */ #define DIALTONE_HZ 425.0 /* dial tone frequency */ -#define TX_PEAK_DIALTONE 16000.0 /* dial tone peak */ +#define TX_PEAK_DIALTONE 0.5 /* dial tone peak FIXME */ #define SUPER_DURATION 0.25 /* duration of supervisory signal measurement */ #define SUPER_DETECT_COUNT 4 /* number of measures to detect supervisory signal */ #define MUTE_DURATION 0.280 /* a tiny bit more than two frames */ @@ -71,9 +84,9 @@ static double super_freq[5] = { }; /* table for fast sine generation */ -static double dsp_tone_bit[2][2][256]; /* polarity, bit, phase */ -static double dsp_sine_super[256]; -static double dsp_sine_dialtone[256]; +static sample_t dsp_tone_bit[2][2][65536]; /* polarity, bit, phase */ +static sample_t dsp_sine_super[65536]; +static sample_t dsp_sine_dialtone[65536]; /* global init for FSK */ void dsp_init(void) @@ -82,8 +95,8 @@ void dsp_init(void) double s; PDEBUG(DDSP, DEBUG_DEBUG, "Generating sine table for supervisory signal.\n"); - for (i = 0; i < 256; i++) { - s = sin((double)i / 256.0 * 2.0 * PI); + for (i = 0; i < 65536; i++) { + s = sin((double)i / 65536.0 * 2.0 * PI); /* supervisor sine */ dsp_sine_super[i] = s * TX_PEAK_SUPER; /* dialtone sine */ @@ -92,7 +105,7 @@ void dsp_init(void) dsp_tone_bit[0][1][i] = s * TX_PEAK_FSK; dsp_tone_bit[1][1][i] = -s * TX_PEAK_FSK; /* bit(0) 1.5 cycles */ - s = sin((double)i / 256.0 * 3.0 * PI); + s = sin((double)i / 65536.0 * 3.0 * PI); dsp_tone_bit[0][0][i] = s * TX_PEAK_FSK; dsp_tone_bit[1][0][i] = -s * TX_PEAK_FSK; } @@ -115,9 +128,8 @@ int dsp_init_sender(nmt_t *nmt) PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Init DSP for Transceiver.\n"); - /* set deviation and modulation parameters */ - nmt->sender.bandwidth = BANDWIDTH; - nmt->sender.sample_deviation = 2500.0 / (double)TX_PEAK_FSK; // FIXME: calc real value + /* set modulation parameters */ + sender_set_fm(&nmt->sender, MAX_DEVIATION, MAX_MODULATION, DBM0_DEVIATION, MAX_DISPLAY); PDEBUG(DDSP, DEBUG_DEBUG, "Using FSK level of %.0f (3.5 KHz deviation @ 1500 Hz)\n", TX_PEAK_FSK); PDEBUG(DDSP, DEBUG_DEBUG, "Using Supervisory level of %.0f (0.3 KHz deviation @ 4015 Hz)\n", TX_PEAK_SUPER); @@ -166,22 +178,22 @@ int dsp_init_sender(nmt_t *nmt) /* count symbols */ for (i = 0; i < 2; i++) audio_goertzel_init(&nmt->fsk_goertzel[i], fsk_freq[i], nmt->sender.samplerate); - nmt->fsk_phaseshift256 = 256.0 / nmt->fsk_samples_per_bit; - PDEBUG(DDSP, DEBUG_DEBUG, "fsk_phaseshift = %.4f\n", nmt->fsk_phaseshift256); + nmt->fsk_phaseshift65536 = 65536.0 / nmt->fsk_samples_per_bit; + PDEBUG(DDSP, DEBUG_DEBUG, "fsk_phaseshift = %.4f\n", nmt->fsk_phaseshift65536); /* count supervidory tones */ for (i = 0; i < 5; i++) { audio_goertzel_init(&nmt->super_goertzel[i], super_freq[i], nmt->sender.samplerate); if (i < 4) { - nmt->super_phaseshift256[i] = 256.0 / ((double)nmt->sender.samplerate / super_freq[i]); - PDEBUG(DDSP, DEBUG_DEBUG, "super_phaseshift[%d] = %.4f\n", i, nmt->super_phaseshift256[i]); + nmt->super_phaseshift65536[i] = 65536.0 / ((double)nmt->sender.samplerate / super_freq[i]); + PDEBUG(DDSP, DEBUG_DEBUG, "super_phaseshift[%d] = %.4f\n", i, nmt->super_phaseshift65536[i]); } } super_reset(nmt); /* dial tone */ - nmt->dial_phaseshift256 = 256.0 / ((double)nmt->sender.samplerate / DIALTONE_HZ); - PDEBUG(DDSP, DEBUG_DEBUG, "dial_phaseshift = %.4f\n", nmt->dial_phaseshift256); + nmt->dial_phaseshift65536 = 65536.0 / ((double)nmt->sender.samplerate / DIALTONE_HZ); + PDEBUG(DDSP, DEBUG_DEBUG, "dial_phaseshift = %.4f\n", nmt->dial_phaseshift65536); /* dtmf */ dtmf_init(&nmt->dtmf, 8000); @@ -305,9 +317,8 @@ static inline void fsk_decode_step(nmt_t *nmt, int pos) level = audio_level(spl, max); /* limit level to prevent division by zero */ - if (level < 0.01) - level = 0.01; -// level = 0.63662 / 2.0; + if (level < 0.001) + level = 0.001; audio_goertzel(nmt->fsk_goertzel, spl, max, pos, result, 2); @@ -353,9 +364,9 @@ static inline void fsk_decode_step(nmt_t *nmt, int pos) printf("|%s|\n", debug_amplitude(quality)); #endif /* adjust level, so a peak level becomes 100% */ - fsk_receive_bit(nmt, bit, quality, level / 0.63662 * 32768.0 / TX_PEAK_FSK); + fsk_receive_bit(nmt, bit, quality, level / 0.63662 / TX_PEAK_FSK); if (nmt->dms_call) - fsk_receive_bit_dms(nmt, bit, quality, level / 0.63662 * 32768.0 / TX_PEAK_FSK); + fsk_receive_bit_dms(nmt, bit, quality, level / 0.63662 / TX_PEAK_FSK); nmt->fsk_filter_sample = 10; } } @@ -368,26 +379,19 @@ static void super_decode(nmt_t *nmt, sample_t *samples, int length) audio_goertzel(&nmt->super_goertzel[nmt->supervisory - 1], samples, length, 0, &result[0], 1); audio_goertzel(&nmt->super_goertzel[4], samples, length, 0, &result[1], 1); /* noise floor detection */ -#if 0 - /* normalize levels */ - result[0] *= 32768.0 / TX_PEAK_SUPER / 0.63662; - result[1] *= 32768.0 / TX_PEAK_SUPER / 0.63662; - printf("signal=%.4f noise=%.4f\n", result[0], result[1]); -#endif - quality = (result[0] - result[1]) / result[0]; if (quality < 0) quality = 0; if (nmt->state == STATE_ACTIVE) - PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Supervisory level %.0f%% quality %.0f%%\n", result[0] / 0.63662 * 32768.0 / TX_PEAK_SUPER * 100.0, quality * 100.0); + PDEBUG_CHAN(DDSP, DEBUG_NOTICE, "Supervisory level %.0f%% quality %.0f%%\n", result[0] / 0.63662 / TX_PEAK_SUPER * 100.0, quality * 100.0); if (quality > 0.5) { if (nmt->super_detected == 0) { nmt->super_detect_count++; if (nmt->super_detect_count == SUPER_DETECT_COUNT) { nmt->super_detected = 1; nmt->super_detect_count = 0; - PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Supervisory signal detected with level=%.0f%%, quality=%.0f%%.\n", result[0] / 0.63662 * 32768.0 / TX_PEAK_SUPER * 100.0, quality * 100.0); + PDEBUG_CHAN(DDSP, DEBUG_DEBUG, "Supervisory signal detected with level=%.0f%%, quality=%.0f%%.\n", result[0] / 0.63662 / TX_PEAK_SUPER * 100.0, quality * 100.0); nmt_rx_super(nmt, 1, quality); } } else @@ -497,21 +501,21 @@ int fsk_render_frame(nmt_t *nmt, const char *frame, int length, sample_t *sample int count = 0, i; polarity = nmt->fsk_polarity; - phaseshift = nmt->fsk_phaseshift256; - phase = nmt->fsk_phase256; + phaseshift = nmt->fsk_phaseshift65536; + phase = nmt->fsk_phase65536; for (i = 0; i < length; i++) { bit = (frame[i] == '1'); do { - *sample++ = dsp_tone_bit[polarity][bit][(uint8_t)phase]; + *sample++ = dsp_tone_bit[polarity][bit][(uint16_t)phase]; count++; phase += phaseshift; - } while (phase < 256.0); - phase -= 256.0; + } while (phase < 65536.0); + phase -= 65536.0; /* flip polarity when we have 1.5 sine waves */ if (bit == 0) polarity = 1 - polarity; } - nmt->fsk_phase256 = phase; + nmt->fsk_phase65536 = phase; nmt->fsk_polarity = polarity; /* return number of samples created for frame */ @@ -570,17 +574,17 @@ static void super_encode(nmt_t *nmt, sample_t *samples, int length) double phaseshift, phase; int i; - phaseshift = nmt->super_phaseshift256[nmt->supervisory - 1]; - phase = nmt->super_phase256; + phaseshift = nmt->super_phaseshift65536[nmt->supervisory - 1]; + phase = nmt->super_phase65536; for (i = 0; i < length; i++) { - *samples++ += dsp_sine_super[(uint8_t)phase]; + *samples++ += dsp_sine_super[(uint16_t)phase]; phase += phaseshift; - if (phase >= 256) - phase -= 256; + if (phase >= 65536) + phase -= 65536; } - nmt->super_phase256 = phase; + nmt->super_phase65536 = phase; } /* Generate audio stream from dial tone. Keep phase for next call of function. */ @@ -589,17 +593,17 @@ static void dial_tone(nmt_t *nmt, sample_t *samples, int length) double phaseshift, phase; int i; - phaseshift = nmt->dial_phaseshift256; - phase = nmt->dial_phase256; + phaseshift = nmt->dial_phaseshift65536; + phase = nmt->dial_phase65536; for (i = 0; i < length; i++) { - *samples++ = dsp_sine_dialtone[(uint8_t)phase]; + *samples++ = dsp_sine_dialtone[(uint16_t)phase]; phase += phaseshift; - if (phase >= 256) - phase -= 256; + if (phase >= 65536) + phase -= 65536; } - nmt->dial_phase256 = phase; + nmt->dial_phase65536 = phase; } /* Provide stream of audio toward radio unit */ diff --git a/src/nmt/nmt.c b/src/nmt/nmt.c index 79c759c..8f22d69 100644 --- a/src/nmt/nmt.c +++ b/src/nmt/nmt.c @@ -1452,7 +1452,7 @@ void nmt_receive_frame(nmt_t *nmt, const char *bits, double quality, double leve frame_t frame; int rc; - PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Quality=%.0f\n", level * 100.0 + 0.5, quality * 100.0 + 0.5); + PDEBUG_CHAN(DDSP, DEBUG_INFO, "RX Level: %.0f%% Quality=%.0f\n", level * 100.0, quality * 100.0); rc = decode_frame(&frame, bits, (nmt->sender.loopback) ? MTX_TO_XX : XX_TO_MTX, (nmt->state == STATE_MT_PAGING)); if (rc < 0) { diff --git a/src/nmt/nmt.h b/src/nmt/nmt.h index 8883bb4..404eadf 100644 --- a/src/nmt/nmt.h +++ b/src/nmt/nmt.h @@ -113,12 +113,12 @@ typedef struct nmt { double fsk_filter_quality[256];/* quality infos */ sample_t *super_filter_spl; /* array with sample buffer for supervisory detection */ int super_filter_pos; /* current sample position in filter_spl */ - double super_phaseshift256[4]; /* how much the phase of sine wave changes per sample */ - double super_phase256; /* current phase */ - double dial_phaseshift256; /* how much the phase of sine wave changes per sample */ - double dial_phase256; /* current phase */ - double fsk_phaseshift256; /* how much the phase of fsk synbol changes per sample */ - double fsk_phase256; /* current phase */ + double super_phaseshift65536[4];/* how much the phase of sine wave changes per sample */ + double super_phase65536; /* current phase */ + double dial_phaseshift65536; /* how much the phase of sine wave changes per sample */ + double dial_phase65536; /* current phase */ + double fsk_phaseshift65536; /* how much the phase of fsk synbol changes per sample */ + double fsk_phase65536; /* current phase */ sample_t *frame_spl; /* samples to store a complete rendered frame */ int frame_size; /* total size of sample buffer */ int frame_length; /* current length of data in sample buffer */ diff --git a/src/test/test_emphasis.c b/src/test/test_emphasis.c index 4d79bc2..445a7d7 100644 --- a/src/test/test_emphasis.c +++ b/src/test/test_emphasis.c @@ -12,7 +12,7 @@ #define SAMPLERATE 48000 -static double get_level(double *samples) +static double get_level(sample_t *samples) { int i; double envelope = 0; @@ -24,7 +24,7 @@ static double get_level(double *samples) return envelope; } -static void gen_samples(double *samples, double freq) +static void gen_samples(sample_t *samples, double freq) { int i; double value; @@ -39,7 +39,7 @@ int main(void) { emphasis_t estate; double cut_off = CUT_OFF_EMPHASIS_DEFAULT; - double samples[SAMPLERATE]; + sample_t samples[SAMPLERATE]; double level; double i; diff --git a/src/test/test_filter.c b/src/test/test_filter.c index 0f7c6b9..e74b403 100644 --- a/src/test/test_filter.c +++ b/src/test/test_filter.c @@ -11,7 +11,7 @@ #define SAMPLERATE 48000 -static double get_level(double *samples) +static double get_level(sample_t *samples) { int i; double envelope = 0; @@ -23,7 +23,7 @@ static double get_level(double *samples) return envelope; } -static void gen_samples(double *samples, double freq) +static void gen_samples(sample_t *samples, double freq) { int i; double value; @@ -38,7 +38,7 @@ int main(void) { filter_t filter_low; filter_t filter_high; - double samples[SAMPLERATE]; + sample_t samples[SAMPLERATE]; double level; int iter = 2; int i;