2016-02-21 17:13:30 +00:00
/* NMT audio processing
*
* ( C ) 2016 by Andreas Eversberg < jolly @ eversberg . eu >
* 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 < http : //www.gnu.org/licenses/>.
*/
2016-08-02 09:03:03 +00:00
# define CHAN nmt->sender.kanal
2016-02-21 17:13:30 +00:00
# include <stdio.h>
# include <stdint.h>
# include <stdlib.h>
# include <string.h>
# include <errno.h>
# include <math.h>
# include "../common/debug.h"
# include "../common/timer.h"
# include "../common/goertzel.h"
# include "nmt.h"
2016-08-17 16:25:48 +00:00
# include "transaction.h"
2016-02-21 17:13:30 +00:00
# include "dsp.h"
# define PI M_PI
2016-08-02 10:53:07 +00:00
/* Notes on frequency deviation of supervidory signal:
*
* 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
*/
2016-07-24 08:26:01 +00:00
/* signaling */
2016-06-20 17:37:56 +00:00
# define COMPANDOR_0DB 32767 /* works quite well */
2016-08-02 10:53:07 +00:00
# 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 */
2016-02-21 17:13:30 +00:00
# define BIT_RATE 1200 /* baud rate */
# define STEPS_PER_BIT 10 /* step every 1/12000 sec */
# define DIALTONE_HZ 425.0 /* dial tone frequency */
# define TX_PEAK_DIALTONE 16000 /* dial tone peak */
# 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 */
2016-07-24 08:26:01 +00:00
/* two signaling tones */
2017-01-07 05:13:31 +00:00
static double fsk_freq [ 2 ] = {
2016-02-21 17:13:30 +00:00
1800.0 ,
1200.0 ,
} ;
/* two supervisory tones */
static double super_freq [ 5 ] = {
3955.0 , /* 0-Signal 1 */
3985.0 , /* 0-Signal 2 */
4015.0 , /* 0-Signal 3 */
4045.0 , /* 0-Signal 4 */
3900.0 , /* noise level to check against */
} ;
/* table for fast sine generation */
2017-01-07 05:13:31 +00:00
uint16_t dsp_tone_bit [ 2 ] [ 2 ] [ 256 ] ; /* polarity, bit, phase */
uint16_t dsp_sine_super [ 256 ] ;
uint16_t dsp_sine_dialtone [ 256 ] ;
2016-02-21 17:13:30 +00:00
/* global init for FSK */
void dsp_init ( void )
{
int i ;
double s ;
2016-03-15 18:26:13 +00:00
PDEBUG ( DDSP , DEBUG_DEBUG , " Generating sine table for supervisory signal. \n " ) ;
2016-02-21 17:13:30 +00:00
for ( i = 0 ; i < 256 ; i + + ) {
s = sin ( ( double ) i / 256.0 * 2.0 * PI ) ;
2017-01-07 05:13:31 +00:00
/* supervisor sine */
2016-02-21 17:13:30 +00:00
dsp_sine_super [ i ] = ( int ) ( s * TX_PEAK_SUPER ) ;
2017-01-07 05:13:31 +00:00
/* dialtone sine */
2016-02-21 17:13:30 +00:00
dsp_sine_dialtone [ i ] = ( int ) ( s * TX_PEAK_DIALTONE ) ;
2017-01-07 05:13:31 +00:00
/* bit(1) 1 cycle */
dsp_tone_bit [ 0 ] [ 1 ] [ i ] = ( int ) ( s * TX_PEAK_FSK ) ;
dsp_tone_bit [ 1 ] [ 1 ] [ i ] = ( int ) ( - s * TX_PEAK_FSK ) ;
/* bit(0) 1.5 cycles */
s = sin ( ( double ) i / 256.0 * 3.0 * PI ) ;
dsp_tone_bit [ 0 ] [ 0 ] [ i ] = ( int ) ( s * TX_PEAK_FSK ) ;
dsp_tone_bit [ 1 ] [ 0 ] [ i ] = ( int ) ( - s * TX_PEAK_FSK ) ;
2016-02-21 17:13:30 +00:00
}
}
/* Init FSK of transceiver */
int dsp_init_sender ( nmt_t * nmt )
{
double coeff ;
int16_t * spl ;
int i ;
2016-03-16 17:21:29 +00:00
/* attack (3ms) and recovery time (13.5ms) according to NMT specs */
2016-06-20 17:37:56 +00:00
init_compandor ( & nmt - > cstate , 8000 , 3.0 , 13.5 , COMPANDOR_0DB ) ;
2016-02-21 17:13:30 +00:00
/* this should not happen. it is implied by previous check */
if ( nmt - > supervisory & & nmt - > sender . samplerate < 12000 ) {
2017-01-07 05:13:31 +00:00
PDEBUG ( DDSP , DEBUG_ERROR , " Sample rate must be at least 12000 Hz to process FSK+supervisory signal. \n " ) ;
2016-02-21 17:13:30 +00:00
return - EINVAL ;
}
2016-08-02 09:03:03 +00:00
PDEBUG_CHAN ( DDSP , DEBUG_DEBUG , " Init DSP for Transceiver. \n " ) ;
2016-02-21 17:13:30 +00:00
2016-08-02 10:53:07 +00:00
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 ) ;
2017-01-07 05:13:31 +00:00
nmt - > fsk_samples_per_bit = ( double ) nmt - > sender . samplerate / ( double ) BIT_RATE ;
nmt - > fsk_bits_per_sample = 1.0 / nmt - > fsk_samples_per_bit ;
PDEBUG ( DDSP , DEBUG_DEBUG , " Use %.4f samples for full bit duration @ %d. \n " , nmt - > fsk_samples_per_bit , nmt - > sender . samplerate ) ;
2016-02-21 17:13:30 +00:00
/* allocate ring buffers, one bit duration */
2017-01-07 05:13:31 +00:00
nmt - > fsk_filter_size = floor ( nmt - > fsk_samples_per_bit ) ; /* buffer holds one bit (rounded down) */
spl = calloc ( 1 , nmt - > fsk_filter_size * sizeof ( * spl ) ) ;
2016-02-21 17:13:30 +00:00
if ( ! spl ) {
2016-03-15 18:26:13 +00:00
PDEBUG ( DDSP , DEBUG_ERROR , " No memory! \n " ) ;
2016-02-21 17:13:30 +00:00
return - ENOMEM ;
}
nmt - > fsk_filter_spl = spl ;
nmt - > fsk_filter_bit = - 1 ;
2017-01-07 05:13:31 +00:00
/* allocate transmit buffer for a complete frame, add 10 to be safe */
nmt - > frame_size = 166.0 * ( double ) nmt - > fsk_samples_per_bit + 10 ;
spl = calloc ( nmt - > frame_size , sizeof ( * spl ) ) ;
2016-02-21 17:13:30 +00:00
if ( ! spl ) {
2016-03-15 18:26:13 +00:00
PDEBUG ( DDSP , DEBUG_ERROR , " No memory! \n " ) ;
2016-02-21 17:13:30 +00:00
return - ENOMEM ;
}
nmt - > frame_spl = spl ;
2017-01-07 05:13:31 +00:00
/* allocate DMS transmit buffer for a complete frame, add 10 to be safe */
nmt - > dms . frame_size = 127.0 * ( double ) nmt - > fsk_samples_per_bit + 10 ;
spl = calloc ( nmt - > dms . frame_size , sizeof ( * spl ) ) ;
2016-07-04 05:23:44 +00:00
if ( ! spl ) {
PDEBUG ( DDSP , DEBUG_ERROR , " No memory! \n " ) ;
return - ENOMEM ;
}
nmt - > dms . frame_spl = spl ;
2016-02-21 17:13:30 +00:00
/* allocate ring buffer for supervisory signal detection */
nmt - > super_samples = ( int ) ( ( double ) nmt - > sender . samplerate * SUPER_DURATION + 0.5 ) ;
2016-06-06 17:41:05 +00:00
spl = calloc ( 1 , nmt - > super_samples * sizeof ( * spl ) ) ;
2016-02-21 17:13:30 +00:00
if ( ! spl ) {
2016-03-15 18:26:13 +00:00
PDEBUG ( DDSP , DEBUG_ERROR , " No memory! \n " ) ;
2016-02-21 17:13:30 +00:00
return - ENOMEM ;
}
nmt - > super_filter_spl = spl ;
/* count symbols */
for ( i = 0 ; i < 2 ; i + + ) {
2017-01-07 05:13:31 +00:00
coeff = 2.0 * cos ( 2.0 * PI * fsk_freq [ i ] / ( double ) nmt - > sender . samplerate ) ;
2016-02-21 17:13:30 +00:00
nmt - > fsk_coeff [ i ] = coeff * 32768.0 ;
2017-01-07 05:13:31 +00:00
PDEBUG ( DDSP , DEBUG_DEBUG , " fsk_coeff[%d] = %d \n " , i , ( int ) nmt - > fsk_coeff [ i ] ) ;
2016-02-21 17:13:30 +00:00
}
2017-01-07 05:13:31 +00:00
nmt - > fsk_phaseshift256 = 256.0 / nmt - > fsk_samples_per_bit ;
PDEBUG ( DDSP , DEBUG_DEBUG , " fsk_phaseshift = %.4f \n " , nmt - > fsk_phaseshift256 ) ;
2016-02-21 17:13:30 +00:00
/* count supervidory tones */
for ( i = 0 ; i < 5 ; i + + ) {
coeff = 2.0 * cos ( 2.0 * PI * super_freq [ i ] / ( double ) nmt - > sender . samplerate ) ;
nmt - > super_coeff [ i ] = coeff * 32768.0 ;
2016-03-15 18:26:13 +00:00
PDEBUG ( DDSP , DEBUG_DEBUG , " supervisory coeff[%d] = %d \n " , i , ( int ) nmt - > super_coeff [ i ] ) ;
2016-02-21 17:13:30 +00:00
if ( i < 4 ) {
nmt - > super_phaseshift256 [ i ] = 256.0 / ( ( double ) nmt - > sender . samplerate / super_freq [ i ] ) ;
2017-01-07 05:13:31 +00:00
PDEBUG ( DDSP , DEBUG_DEBUG , " super_phaseshift[%d] = %.4f \n " , i , nmt - > super_phaseshift256 [ i ] ) ;
2016-02-21 17:13:30 +00:00
}
}
super_reset ( nmt ) ;
/* dial tone */
nmt - > dial_phaseshift256 = 256.0 / ( ( double ) nmt - > sender . samplerate / DIALTONE_HZ ) ;
2017-01-07 05:13:31 +00:00
PDEBUG ( DDSP , DEBUG_DEBUG , " dial_phaseshift = %.4f \n " , nmt - > dial_phaseshift256 ) ;
2016-02-21 17:13:30 +00:00
/* dtmf */
dtmf_init ( & nmt - > dtmf , 8000 ) ;
return 0 ;
}
/* Cleanup transceiver instance. */
void dsp_cleanup_sender ( nmt_t * nmt )
{
2016-12-09 15:34:33 +00:00
PDEBUG_CHAN ( DDSP , DEBUG_DEBUG , " Cleanup DSP for Transceiver. \n " ) ;
2016-02-21 17:13:30 +00:00
if ( nmt - > frame_spl ) {
free ( nmt - > frame_spl ) ;
nmt - > frame_spl = NULL ;
}
2016-07-04 05:23:44 +00:00
if ( nmt - > dms . frame_spl ) {
free ( nmt - > dms . frame_spl ) ;
nmt - > dms . frame_spl = NULL ;
}
2016-02-21 17:13:30 +00:00
if ( nmt - > fsk_filter_spl ) {
free ( nmt - > fsk_filter_spl ) ;
nmt - > fsk_filter_spl = NULL ;
}
if ( nmt - > super_filter_spl ) {
free ( nmt - > super_filter_spl ) ;
nmt - > super_filter_spl = NULL ;
}
}
/* Check for SYNC bits, then collect data bits */
static void fsk_receive_bit ( nmt_t * nmt , int bit , double quality , double level )
{
double frames_elapsed ;
2016-04-24 05:12:21 +00:00
int i ;
2016-02-21 17:13:30 +00:00
// printf("bit=%d quality=%.4f\n", bit, quality);
if ( ! nmt - > fsk_filter_in_sync ) {
nmt - > fsk_filter_sync = ( nmt - > fsk_filter_sync < < 1 ) | bit ;
2016-04-24 05:12:21 +00:00
/* level and quality */
nmt - > fsk_filter_level [ nmt - > fsk_filter_count & 0xff ] = level ;
nmt - > fsk_filter_quality [ nmt - > fsk_filter_count & 0xff ] = quality ;
nmt - > fsk_filter_count + + ;
2016-02-21 17:13:30 +00:00
/* check if pattern 1010111100010010 matches */
if ( nmt - > fsk_filter_sync ! = 0xaf12 )
return ;
2016-04-24 05:12:21 +00:00
/* average level and quality */
level = quality = 0 ;
for ( i = 0 ; i < 16 ; i + + ) {
level + = nmt - > fsk_filter_level [ ( nmt - > fsk_filter_count - 1 - i ) & 0xff ] ;
quality + = nmt - > fsk_filter_quality [ ( nmt - > fsk_filter_count - 1 - i ) & 0xff ] ;
}
level / = 16.0 ; quality / = 16.0 ;
// printf("sync (level = %.2f, quality = %.2f\n", level, quality);
/* do not accept garbage */
if ( quality < 0.65 )
return ;
2016-02-21 17:13:30 +00:00
/* sync time */
2017-01-07 05:13:31 +00:00
nmt - > rx_bits_count_last = nmt - > rx_bits_count_current ;
nmt - > rx_bits_count_current = nmt - > rx_bits_count - 26.0 ;
2016-02-21 17:13:30 +00:00
/* rest sync register */
nmt - > fsk_filter_sync = 0 ;
nmt - > fsk_filter_in_sync = 1 ;
nmt - > fsk_filter_count = 0 ;
/* set muting of receive path */
nmt - > fsk_filter_mute = ( int ) ( ( double ) nmt - > sender . samplerate * MUTE_DURATION ) ;
return ;
}
/* read bits */
2016-04-24 05:12:21 +00:00
nmt - > fsk_filter_frame [ nmt - > fsk_filter_count ] = bit + ' 0 ' ;
nmt - > fsk_filter_level [ nmt - > fsk_filter_count ] = level ;
nmt - > fsk_filter_quality [ nmt - > fsk_filter_count ] = quality ;
if ( + + nmt - > fsk_filter_count ! = 140 )
2016-02-21 17:13:30 +00:00
return ;
/* end of frame */
nmt - > fsk_filter_frame [ 140 ] = ' \0 ' ;
nmt - > fsk_filter_in_sync = 0 ;
2016-04-24 05:12:21 +00:00
/* average level and quality */
level = quality = 0 ;
for ( i = 0 ; i < 140 ; i + + ) {
level + = nmt - > fsk_filter_level [ i ] ;
quality + = nmt - > fsk_filter_quality [ i ] ;
}
level / = 140.0 ; quality / = 140.0 ;
2016-02-21 17:13:30 +00:00
/* send telegramm */
2017-01-07 05:13:31 +00:00
frames_elapsed = ( nmt - > rx_bits_count_current - nmt - > rx_bits_count_last ) / 166.0 ;
2016-04-23 12:33:02 +00:00
/* convert level so that received level at TX_PEAK_FSK results in 1.0 (100%) */
2016-07-04 05:23:44 +00:00
nmt_receive_frame ( nmt , nmt - > fsk_filter_frame , quality , level , frames_elapsed ) ;
2016-02-21 17:13:30 +00:00
}
//#define DEBUG_MODULATOR
//#define DEBUG_FILTER
//#define DEBUG_QUALITY
/* Filter one chunk of audio an detect tone, quality and loss of signal.
2017-01-07 05:13:31 +00:00
* The chunk is a window of 1 / 1200 s . This window slides over audio stream
* and is processed every 1 / 12000 s . ( one step ) */
2016-02-21 17:13:30 +00:00
static inline void fsk_decode_step ( nmt_t * nmt , int pos )
{
double level , result [ 2 ] , softbit , quality ;
int max ;
int16_t * spl ;
int bit ;
2017-01-07 05:13:31 +00:00
max = nmt - > fsk_filter_size ;
2016-02-21 17:13:30 +00:00
spl = nmt - > fsk_filter_spl ;
2017-01-07 05:13:31 +00:00
/* count time in bits */
nmt - > rx_bits_count + = 0.1 ;
2016-02-21 17:13:30 +00:00
level = audio_level ( spl , max ) ;
2016-05-01 08:23:45 +00:00
/* limit level to prevent division by zero */
if ( level < 0.01 )
level = 0.01 ;
2016-02-21 17:13:30 +00:00
// level = 0.63662 / 2.0;
audio_goertzel ( spl , max , pos , nmt - > fsk_coeff , result , 2 ) ;
/* calculate soft bit from both frequencies */
softbit = ( result [ 1 ] / level - result [ 0 ] / level + 1.0 ) / 2.0 ;
2016-05-01 08:23:45 +00:00
//printf("%.3f: %.3f\n", level, softbit);
2016-02-21 17:13:30 +00:00
/* scale it, since both filters overlap by some percent */
# define MIN_QUALITY 0.33
softbit = ( softbit - MIN_QUALITY ) / ( 1.0 - MIN_QUALITY - MIN_QUALITY ) ;
# ifdef DEBUG_FILTER
2016-05-15 18:31:42 +00:00
// printf("|%s", debug_amplitude(result[0]/level));
// printf("|%s| low=%.3f high=%.3f level=%d\n", debug_amplitude(result[1]/level), result[0]/level, result[1]/level, (int)level);
printf ( " |%s| softbit=%.3f \n " , debug_amplitude ( softbit ) , softbit ) ;
2016-02-21 17:13:30 +00:00
# endif
2016-05-01 08:23:45 +00:00
if ( softbit > 1 )
softbit = 1 ;
if ( softbit < 0 )
softbit = 0 ;
2016-02-21 17:13:30 +00:00
if ( softbit > 0.5 )
bit = 1 ;
else
bit = 0 ;
if ( nmt - > fsk_filter_bit ! = bit ) {
2016-05-01 08:23:45 +00:00
/* if we have a bit change, reset sample counter to one half bit duration */
2016-02-21 17:13:30 +00:00
# ifdef DEBUG_FILTER
puts ( " bit change " ) ;
# endif
nmt - > fsk_filter_bit = bit ;
nmt - > fsk_filter_sample = 5 ;
} else if ( - - nmt - > fsk_filter_sample = = 0 ) {
2016-05-01 08:23:45 +00:00
/* if sample counter bit reaches 0, we reset sample counter to one bit duration */
2016-02-21 17:13:30 +00:00
# ifdef DEBUG_FILTER
puts ( " sample " ) ;
# endif
// quality = result[bit] / level;
if ( softbit > 0.5 )
quality = softbit * 2.0 - 1.0 ;
else
quality = 1.0 - softbit * 2.0 ;
# ifdef DEBUG_QUALITY
2016-05-15 18:31:42 +00:00
printf ( " |%s| quality=%.2f " , debug_amplitude ( softbit ) , quality ) ;
printf ( " |%s| \n " , debug_amplitude ( quality ) ) ;
2016-02-21 17:13:30 +00:00
# endif
/* adjust level, so a peak level becomes 100% */
2016-07-04 05:23:44 +00:00
fsk_receive_bit ( nmt , bit , quality , level / 0.63662 * 32768.0 / TX_PEAK_FSK ) ;
if ( nmt - > dms_call )
fsk_receive_bit_dms ( nmt , bit , quality , level / 0.63662 * 32768.0 / TX_PEAK_FSK ) ;
2016-02-21 17:13:30 +00:00
nmt - > fsk_filter_sample = 10 ;
}
}
/* compare supervisory signal against noise floor on 3900 Hz */
static void super_decode ( nmt_t * nmt , int16_t * samples , int length )
{
int coeff [ 2 ] ;
double result [ 2 ] , quality ;
coeff [ 0 ] = nmt - > super_coeff [ nmt - > supervisory - 1 ] ;
coeff [ 1 ] = nmt - > super_coeff [ 4 ] ; /* noise floor detection */
audio_goertzel ( samples , length , 0 , coeff , result , 2 ) ;
#if 0
/* normalize levels */
2016-04-23 12:33:02 +00:00
result [ 0 ] * = 32768.0 / TX_PEAK_SUPER / 0.63662 ;
result [ 1 ] * = 32768.0 / TX_PEAK_SUPER / 0.63662 ;
2016-02-21 17:13:30 +00:00
printf ( " signal=%.4f noise=%.4f \n " , result [ 0 ] , result [ 1 ] ) ;
# endif
quality = ( result [ 0 ] - result [ 1 ] ) / result [ 0 ] ;
if ( quality < 0 )
quality = 0 ;
2016-08-02 10:53:07 +00:00
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 ) ;
2016-02-21 17:13:30 +00:00
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 ;
2016-08-02 10:53:07 +00:00
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 ) ;
2016-02-21 17:13:30 +00:00
nmt_rx_super ( nmt , 1 , quality ) ;
}
} else
nmt - > super_detect_count = 0 ;
} else {
if ( nmt - > super_detected = = 1 ) {
nmt - > super_detect_count + + ;
if ( nmt - > super_detect_count = = SUPER_DETECT_COUNT ) {
nmt - > super_detected = 0 ;
nmt - > super_detect_count = 0 ;
2016-08-02 09:03:03 +00:00
PDEBUG_CHAN ( DDSP , DEBUG_DEBUG , " Supervisory signal lost. \n " ) ;
2016-02-21 17:13:30 +00:00
nmt_rx_super ( nmt , 0 , 0.0 ) ;
}
} else
nmt - > super_detect_count = 0 ;
}
}
/* Reset supervisory detection states, so ongoing tone will be detected again. */
void super_reset ( nmt_t * nmt )
{
2016-08-02 09:03:03 +00:00
PDEBUG_CHAN ( DDSP , DEBUG_DEBUG , " Supervisory detector reset. \n " ) ;
2016-02-21 17:13:30 +00:00
nmt - > super_detected = 0 ;
nmt - > super_detect_count = 0 ;
}
/* Process received audio stream from radio unit. */
void sender_receive ( sender_t * sender , int16_t * samples , int length )
{
nmt_t * nmt = ( nmt_t * ) sender ;
int16_t * spl ;
2017-01-07 05:13:31 +00:00
int max , pos ;
double step , bps ;
2016-02-21 17:13:30 +00:00
int i ;
/* write received samples to decode buffer */
max = nmt - > super_samples ;
spl = nmt - > super_filter_spl ;
pos = nmt - > super_filter_pos ;
for ( i = 0 ; i < length ; i + + ) {
spl [ pos + + ] = samples [ i ] ;
if ( pos = = max ) {
pos = 0 ;
if ( nmt - > supervisory )
super_decode ( nmt , spl , max ) ;
}
}
nmt - > super_filter_pos = pos ;
/* write received samples to decode buffer */
2017-01-07 05:13:31 +00:00
max = nmt - > fsk_filter_size ;
2016-02-21 17:13:30 +00:00
pos = nmt - > fsk_filter_pos ;
step = nmt - > fsk_filter_step ;
2017-01-07 05:13:31 +00:00
bps = nmt - > fsk_bits_per_sample ;
2016-02-21 17:13:30 +00:00
spl = nmt - > fsk_filter_spl ;
for ( i = 0 ; i < length ; i + + ) {
# ifdef DEBUG_MODULATOR
2016-05-15 18:31:42 +00:00
printf ( " |%s| \n " , debug_amplitude ( ( double ) samples [ i ] / TX_PEAK_FSK / 2.0 ) ) ;
2016-02-21 17:13:30 +00:00
# endif
2017-01-07 05:13:31 +00:00
/* write into ring buffer */
2016-02-21 17:13:30 +00:00
spl [ pos + + ] = samples [ i ] ;
2017-01-07 05:13:31 +00:00
if ( pos = = max )
pos = 0 ;
/* muting audio while receiving frame */
if ( nmt - > fsk_filter_mute & & ! nmt - > sender . loopback ) {
2016-02-21 17:13:30 +00:00
samples [ i ] = 0 ;
nmt - > fsk_filter_mute - - ;
}
2017-01-07 05:13:31 +00:00
/* if 1/10th of a bit duration is reached, decode buffer */
step + = bps ;
if ( step > = 0.1 ) {
step - = 0.1 ;
2016-02-21 17:13:30 +00:00
fsk_decode_step ( nmt , pos ) ;
}
}
2017-01-07 05:13:31 +00:00
nmt - > fsk_filter_step = step ;
2016-02-21 17:13:30 +00:00
nmt - > fsk_filter_pos = pos ;
if ( ( nmt - > dsp_mode = = DSP_MODE_AUDIO | | nmt - > dsp_mode = = DSP_MODE_DTMF )
2016-08-17 16:25:48 +00:00
& & nmt - > trans & & nmt - > trans - > callref ) {
2016-02-21 17:13:30 +00:00
int16_t down [ length ] ; /* more than enough */
int count ;
count = samplerate_downsample ( & nmt - > sender . srstate , samples , length , down ) ;
2016-06-20 17:37:56 +00:00
if ( nmt - > compandor )
2016-02-21 17:13:30 +00:00
expand_audio ( & nmt - > cstate , down , count ) ;
if ( nmt - > dsp_mode = = DSP_MODE_DTMF )
dtmf_tone ( & nmt - > dtmf , down , count ) ;
spl = nmt - > sender . rxbuf ;
pos = nmt - > sender . rxbuf_pos ;
for ( i = 0 ; i < count ; i + + ) {
2016-04-23 16:50:11 +00:00
spl [ pos + + ] = down [ i ] ;
2016-02-21 17:13:30 +00:00
if ( pos = = 160 ) {
2016-08-17 16:25:48 +00:00
call_tx_audio ( nmt - > trans - > callref , spl , 160 ) ;
2016-02-21 17:13:30 +00:00
pos = 0 ;
}
}
nmt - > sender . rxbuf_pos = pos ;
} else
nmt - > sender . rxbuf_pos = 0 ;
}
2016-07-04 05:23:44 +00:00
/* render frame */
2017-01-07 05:13:31 +00:00
int fsk_render_frame ( nmt_t * nmt , const char * frame , int length , int16_t * sample )
2016-07-04 05:23:44 +00:00
{
int bit , polarity ;
2017-01-07 05:13:31 +00:00
double phaseshift , phase ;
int count = 0 , i ;
2016-07-04 05:23:44 +00:00
polarity = nmt - > fsk_polarity ;
2017-01-07 05:13:31 +00:00
phaseshift = nmt - > fsk_phaseshift256 ;
phase = nmt - > fsk_phase256 ;
2016-07-04 05:23:44 +00:00
for ( i = 0 ; i < length ; i + + ) {
bit = ( frame [ i ] = = ' 1 ' ) ;
2017-01-07 05:13:31 +00:00
do {
* sample + + = dsp_tone_bit [ polarity ] [ bit ] [ ( ( uint8_t ) phase ) & 0xff ] ;
count + + ;
phase + = phaseshift ;
} while ( phase < 256.0 ) ;
phase - = 256.0 ;
2016-07-04 05:23:44 +00:00
/* flip polarity when we have 1.5 sine waves */
if ( bit = = 0 )
polarity = 1 - polarity ;
}
2017-01-07 05:13:31 +00:00
nmt - > fsk_phase256 = phase ;
2016-07-04 05:23:44 +00:00
nmt - > fsk_polarity = polarity ;
2017-01-07 05:13:31 +00:00
/* return number of samples created for frame */
return count ;
2016-07-04 05:23:44 +00:00
}
2016-02-21 17:13:30 +00:00
static int fsk_frame ( nmt_t * nmt , int16_t * samples , int length )
{
const char * frame ;
2016-07-04 05:23:44 +00:00
int16_t * spl ;
2016-02-21 17:13:30 +00:00
int i ;
int count , max ;
next_frame :
2017-01-07 05:13:31 +00:00
if ( ! nmt - > frame_length ) {
2016-02-21 17:13:30 +00:00
/* request frame */
frame = nmt_get_frame ( nmt ) ;
if ( ! frame ) {
2016-08-02 09:03:03 +00:00
PDEBUG_CHAN ( DDSP , DEBUG_DEBUG , " Stop sending frames. \n " ) ;
2016-02-21 17:13:30 +00:00
return length ;
}
/* render frame */
2017-01-07 05:13:31 +00:00
nmt - > frame_length = fsk_render_frame ( nmt , frame , 166 , nmt - > frame_spl ) ;
nmt - > frame_pos = 0 ;
if ( nmt - > frame_length > nmt - > frame_size ) {
PDEBUG_CHAN ( DDSP , DEBUG_ERROR , " Frame exceeds buffer, please fix! \n " ) ;
abort ( ) ;
}
2016-02-21 17:13:30 +00:00
}
/* send audio from frame */
2017-01-07 05:13:31 +00:00
max = nmt - > frame_length ;
2016-02-21 17:13:30 +00:00
count = max - nmt - > frame_pos ;
if ( count > length )
count = length ;
spl = nmt - > frame_spl + nmt - > frame_pos ;
for ( i = 0 ; i < count ; i + + ) {
* samples + + = * spl + + ;
}
length - = count ;
nmt - > frame_pos + = count ;
/* check for end of telegramm */
if ( nmt - > frame_pos = = max ) {
2017-01-07 05:13:31 +00:00
nmt - > frame_length = 0 ;
2016-02-21 17:13:30 +00:00
/* we need more ? */
if ( length )
goto next_frame ;
}
return length ;
}
/* Generate audio stream with supervisory signal. Keep phase for next call of function. */
static void super_encode ( nmt_t * nmt , int16_t * samples , int length )
{
double phaseshift , phase ;
int32_t sample ;
int i ;
phaseshift = nmt - > super_phaseshift256 [ nmt - > supervisory - 1 ] ;
phase = nmt - > super_phase256 ;
for ( i = 0 ; i < length ; i + + ) {
sample = * samples ;
sample + = dsp_sine_super [ ( ( uint8_t ) phase ) & 0xff ] ;
if ( sample > 32767 )
sample = 32767 ;
else if ( sample < - 32767 )
sample = - 32767 ;
* samples + + = sample ;
phase + = phaseshift ;
if ( phase > = 256 )
phase - = 256 ;
}
nmt - > super_phase256 = phase ;
}
/* Generate audio stream from dial tone. Keep phase for next call of function. */
static void dial_tone ( nmt_t * nmt , int16_t * samples , int length )
{
double phaseshift , phase ;
int i ;
phaseshift = nmt - > dial_phaseshift256 ;
phase = nmt - > dial_phase256 ;
for ( i = 0 ; i < length ; i + + ) {
* samples + + = dsp_sine_dialtone [ ( ( uint8_t ) phase ) & 0xff ] ;
phase + = phaseshift ;
if ( phase > = 256 )
phase - = 256 ;
}
nmt - > dial_phase256 = phase ;
}
/* Provide stream of audio toward radio unit */
void sender_send ( sender_t * sender , int16_t * samples , int length )
{
nmt_t * nmt = ( nmt_t * ) sender ;
int len ;
again :
switch ( nmt - > dsp_mode ) {
case DSP_MODE_AUDIO :
case DSP_MODE_DTMF :
2017-01-04 13:14:02 +00:00
jitter_load ( & nmt - > sender . dejitter , samples , length ) ;
2016-07-04 05:23:44 +00:00
/* send after dejitter, so audio is flushed */
if ( nmt - > dms . frame_valid ) {
fsk_dms_frame ( nmt , samples , length ) ;
break ;
}
2016-02-21 17:13:30 +00:00
if ( nmt - > supervisory )
super_encode ( nmt , samples , length ) ;
break ;
case DSP_MODE_DIALTONE :
dial_tone ( nmt , samples , length ) ;
break ;
case DSP_MODE_SILENCE :
memset ( samples , 0 , length * sizeof ( * samples ) ) ;
break ;
case DSP_MODE_FRAME :
/* Encode frame into audio stream. If frames have
* stopped , process again for rest of stream . */
len = fsk_frame ( nmt , samples , length ) ;
/* special case: add supervisory signal to frame at loop test */
if ( nmt - > sender . loopback & & nmt - > supervisory )
super_encode ( nmt , samples , length ) ;
if ( len ) {
samples + = length - len ;
length = len ;
goto again ;
}
break ;
}
}
2016-12-09 15:34:33 +00:00
const char * nmt_dsp_mode_name ( enum dsp_mode mode )
{
static char invalid [ 16 ] ;
switch ( mode ) {
case DSP_MODE_SILENCE :
return " SILENCE " ;
case DSP_MODE_DIALTONE :
return " DIALTONE " ;
case DSP_MODE_AUDIO :
return " AUDIO " ;
case DSP_MODE_FRAME :
return " FRAME " ;
case DSP_MODE_DTMF :
return " DTMF " ;
}
sprintf ( invalid , " invalid(%d) " , mode ) ;
return invalid ;
}
2016-02-21 17:13:30 +00:00
void nmt_set_dsp_mode ( nmt_t * nmt , enum dsp_mode mode )
{
/* reset telegramm */
if ( mode = = DSP_MODE_FRAME & & nmt - > dsp_mode ! = mode )
2017-01-07 05:13:31 +00:00
nmt - > frame_length = 0 ;
2016-06-04 13:14:20 +00:00
2016-12-09 15:34:33 +00:00
PDEBUG_CHAN ( DDSP , DEBUG_DEBUG , " DSP mode %s -> %s \n " , nmt_dsp_mode_name ( nmt - > dsp_mode ) , nmt_dsp_mode_name ( mode ) ) ;
2016-02-21 17:13:30 +00:00
nmt - > dsp_mode = mode ;
}