[digital signal] DTMF signal generation and detection based on Matlab GUI (with key tone) [including Matlab source code phase 1086]

Posted by kalaszabi on Wed, 26 Jan 2022 07:34:48 +0100

1, Introduction

1 meaning
Dual Tone Multi Frequency DTMF (Dual Tone Multi Frequency) is composed of high-frequency group and low-frequency group, and the high-frequency group and low-frequency group each contain four frequencies. A high-frequency signal and a low-frequency signal are superimposed to form a combined signal, representing a number. DTMF signaling has 16 codes. DTMF signaling can be used to call the corresponding interphone.
Dual tone multifrequency signal (DTMF), a kind of user signaling between telephone and exchange in telephone system, is usually used to send the called number.

Before using DTMF signals, the telephone system uses a series of intermittent pulses to transmit the called number, which is called pulse dialing. Pulse dialing requires operators in the telecommunications bureau to manually complete long-distance connection.
Dual tone multifrequency signal was invented by Bell Labs. Its purpose is to automatically complete long-distance calls.
DTMF dialing keyboard is 4 × 4 matrix, each row represents a low frequency and each column represents a high frequency. Each press of a key sends a combination of high-frequency and low-frequency sinusoidal signals. For example, '1' is equivalent to 697 and 1209 Hz (Hz). The switch can decode these frequency combinations and determine the corresponding keys.

The DTMF codec converts the keystroke or digital information into a two tone signal and sends it during encoding, and detects the existence of keystroke or digital information in the received DTMF signal during decoding. A DTMF signal is composed of audio signals of two frequencies superimposed. The frequencies of the two audio signals come from two pre allocated frequency groups: row frequency group or column frequency group. Each pair of such audio signals uniquely represents a number or symbol. There are usually 16 keys in the telephone, including 10 numeric keys 0 ~ 9 and 6 function keys *, #, a, B, C and D. According to the combination principle, there are generally 8 different single audio signals. Therefore, there are also 8 kinds of frequencies that can be used, so it is called multi frequency. Because it uses any combination of 2 out of 8 frequencies for coding, it is also called "2 out of 8" coding technology. According to CCITT's recommendations, 8 frequencies are adopted internationally, including 687Hz, 770Hz, 852Hz, 941Hz, 1209Hz, 1336Hz, 1477Hz and 1633Hz. 16 different combinations can be formed with these 8 frequencies to represent 16 different numbers or function keys. See Table 1 for specific combinations.

Tone detection is required in many applications, such as dual tone multi frequency signal (DTMF) decoding, call process (dial tone, busy tone, etc.) decoding, and frequency response test (send a tone and read the result back at the same time). In the frequency response test, if the measurement is carried out within a certain frequency range, the obtained frequency response curve may contain rich information. For example, from the frequency response curve of the telephone line, we can know whether there is a load coil (inductance) on the line.
Although there are special IC s for the above applications, the cost of using software to realize the functions of these chips is much lower than that of using special chips. However, many embedded systems do not have the ability of continuous real-time FFT processing, so Goertzel algorithm is suitable. This paper will discuss Goertzel basic algorithm and Goertzel optimization algorithm.
Using Goertzel's basic algorithm, the same real and imaginary parts of frequency as conventional discrete Fourier transform (DFT) or FFT can be obtained. If necessary, the amplitude and phase information can also be calculated from the real and imaginary parts of the frequency. Goertzel optimization algorithm is faster and simpler than Goertzel basic algorithm, but Goertzel optimization algorithm does not give the real and imaginary components of frequency, it can only give the relevant amplitude square. If the amplitude information is needed, it can be obtained by prescribing the result, but the phase information cannot be obtained by this method.

2 Goertzel basic algorithm
Goertzel basic algorithm is processed immediately after each sampling, and tone detection is performed once in each nth sampling. When using FFT algorithm, we need to process the samples in blocks, but this does not mean that we must process the data in blocks. The time of digital processing is very short, so if there is an interrupt for each sampling, these digital processing can be completed in the interrupt service program (ISR). Alternatively, if there is a sampling cache in the system, you can continuously sample and then batch.
Before actually running Goertzel algorithm, the following preliminary calculation must be carried out:

  1. Determine the sampling rate;
  2. Select the block size, i.e. N;
  3. Perform a cosine and sine calculation in advance;
  4. Calculate a coefficient in advance.
    These calculations can be completed in advance and then hard coded into the program, so as to save RAM and ROM space, and can also be calculated dynamically.

3 select the appropriate sampling rate
In fact, the sampling rate may have been determined by the application itself. For example, 8kHz sampling rate is widely used in telecommunication applications, that is, 8000 samples per second. For another example, the operating frequency of an analog-to-digital converter (or codec) may be determined by an external clock or external crystal oscillator that we cannot control.
However, if we can choose the sampling rate, we must follow Nyquist sampling theorem: the sampling rate is not less than twice the maximum signal frequency. This is because if we want to detect multiple frequencies, using a higher sampling rate may get better results. Moreover, we all hope that there is an integer multiple relationship between the sampling rate and each frequency of interest.

4 block size setting
The block size n in Goertzel algorithm is similar to the number of points in the corresponding FFT, which controls the size of frequency resolution. For example, if the sampling rate is 8kHz and N is 100 samples, the frequency resolution is 80Hz.
This makes it possible for us to take n as high as possible in order to obtain the maximum frequency resolution. However, the larger the N, the more time it takes to detect each tone, because we must wait until all the n samples are completed before we can start processing. For example, when the sampling rate is 8kHz, it takes 100ms to accumulate 800 samples. If you want to shorten the time of detecting tones, you must adjust the value of N appropriately.
Another factor affecting the selection of n is the relationship between sampling rate and target frequency. Ideally, the target frequency is within the midpoint of the corresponding frequency resolution, that is, we want the target frequency to be sample_ An integral multiple of the rate / N ratio. Fortunately, N in Goertzel algorithm is different from that in FFT, and does not have to be an integer power of 2.

5 pre calculated constant
After the sampling rate and block size are determined, the constants required for processing only need to be calculated through the following five simple calculations:
k = (Ntarget_freq)/sample_tate
w = (2π/N)*k
cosine = cos w
sine = sin w
coeff = 2 * cosine
Each sampling process requires three variables, which we call Q0 ', Q1' and Q2. Q1 is the Q0 value of the previous sampling process, and Q2 is the Q0 value before two sampling (or the value of Q1 before this sampling).
Q1 and Q2 must be initialized to 0 at the beginning of each sampling block. Each sample needs to be calculated according to the following three equations:
Q0 = coeff * Q1 - Q2 + sample
Q2 = Q1
Q1 = Q0
After N pre sampling calculations, the presence of tones can be detected.
real = (Q1 - Q2 * cosine)
imag = (Q2 * sine)
magnitude2 = real2 + imag2
At this time, it only needs a simple amplitude threshold test to judge whether there is a tone. After that, reset Q2 and Q1 to 0 and start the processing of the next block.

6 Goertzel optimization algorithm
Goertzel optimization algorithm needs less computation than Goertzel basic algorithm, but it is at the cost of losing phase information.
In Goertzel optimization algorithm, each sampling processing is exactly the same, but the processing result is different from Goertzel basic algorithm. In Goertzel's basic algorithm, it is usually necessary to calculate the real part and imaginary part of the signal, and then convert the calculation results of the real part and imaginary part into the corresponding amplitude square. In the optimized Goertzel algorithm, the real part and imaginary part do not need to be calculated, and the following formula is calculated directly:
magnitude2 = Q12 + Q22-Q1Q2coeff

2, Source code

function varargout = GUI(varargin)
%          GUI Application M-file for GUI.fig
%        FIG = GUI launch GUI GUI.
%              GUI('callback_name', ...) invoke the named callback.
%
%  Date: 21/05/04     Time: 17:50          
%  Email: pranamjanney@yahoo.com

if nargin == 0  % LAUNCH GUI

	fig = openfig(mfilename,'reuse');

	% Use system color scheme for figure:
	set(fig,'Color',get(0,'defaultUicontrolBackgroundColor'));

	% Generate a structure of handles to pass to callbacks, and store it. 
	handles = guihandles(fig);
    
    % Initialising structure variables to be used in program
    handles.data = 0;           % used for storing the Num_of_samples value
    handles.data1 = 0;          % used for storing the Slider values
    handles.data3 = 0;          % used for storing the number of times the push button is pressed
    handles.data4(1,8) = ' ';       % Array to store the numbers dialled 
	handles.chk = 0;            %  To check if the Number of samples is used or not
    
    guidata(fig, handles);

	if nargout > 0
		varargout{1} = fig;
	end

elseif ischar(varargin{1}) % INVOKE NAMED SUBFUNCTION OR CALLBACK

	try
		if (nargout)
			[varargout{1:nargout}] = feval(varargin{:}); % FEVAL switchyard
		else
			feval(varargin{:}); % FEVAL switchyard
		end
	catch
		disp(lasterr);
	end

end

% --------------------------------------------------------------------
function varargout = pushbutton1_Callback(h, eventdata, handles, varargin)

% To check for N
if handles.chk == 0
    N = 205;
else
    N = handles.data;           %  Number of samples
end

NP = handles.data1;         % Noise Power
handles.data3 = handles.data3 + 1;  % to keep track of number of times push buttons are used

% Generator
[x,v,snr] = generator(1,N,NP);
size(x);

% Display SNR
set(handles.edit3,'String',snr)

% To plot on GUI
f = 1:N;
axes(handles.Out_dtmf) % Select the proper axes
plot(f,x(1:N))
set(handles.Out_dtmf,'XMinorTick','on')
grid on

% Decoder
[D,m] = decoder(x,N);
size(m);

% To append each dialled digit into an array (max 8 numbers)
[handles.data4,handles.data3] = StringNum(handles.data4,D,handles.data3);

% After 8th digit the next number is put into first digit place
if handles.data4 == ' ' 
    handles.data4(handles.data3) = D;
end

% To display the dialled numbers 
set(handles.edit2,'String',handles.data4);         % The dialled number as decoded by the decoder
                                       % is displayed on the edit text

% To plot the output                                       
f = 1 : length(m);
axes(handles.G_output) % Select the proper axes
plot(f,m)
set(handles.G_output,'XMinorTick','on')
grid on
guidata(h,handles);



% --------------------------------------------------------------------
function varargout = pushbutton2_Callback(h, eventdata, handles, varargin)

% To check for N
if handles.chk == 0
    N = 205;
else
    N = handles.data;           %  Number of samples
end       %  Number of samples

NP = handles.data1;         % Noise Power
handles.data3 = handles.data3 + 1;  % to keep track of number of times push buttons are used

% Generator
[x,v,snr] = generator(2,N,NP);
size(x);

% Display SNR
set(handles.edit3,'String',snr)

% To plot on GUI
f = 1:N;
axes(handles.Out_dtmf) % Select the proper axes
plot(f,x(1:N))
set(handles.Out_dtmf,'XMinorTick','on')
grid on

% Decoder
[D,m] = decoder(x,N);
size(m);

% To append each dialled digit into an array (max 8 numbers)
[handles.data4,handles.data3] = StringNum(handles.data4,D,handles.data3);

% After 8th digit the next number is put into first digit place
if handles.data4 == ' ' 
    handles.data4(handles.data3) = D;
end

% To display the dialled numbers 
set(handles.edit2,'String',handles.data4);         % The dialled number as decoded by the decoder
                                       % is displayed on the edit text

% To plot the output                                       
f = 1 : length(m);
axes(handles.G_output) % Select the proper axes
plot(f,m)
set(handles.G_output,'XMinorTick','on')
grid on
guidata(h,handles);



% --------------------------------------------------------------------
function varargout = pushbutton3_Callback(h, eventdata, handles, varargin)

% To check for N
if handles.chk == 0
    N = 205;
else
    N = handles.data;           %  Number of samples
end


NP = handles.data1;         % Noise Power
handles.data3 = handles.data3 + 1;  % to keep track of number of times push buttons are used

% Generator
[x,v,snr] = generator('A',N,NP);
size(x);

% Display SNR
set(handles.edit3,'String',snr)

% To plot on GUI
f = 1:N;
axes(handles.Out_dtmf) % Select the proper axes
plot(f,x(1:N))
set(handles.Out_dtmf,'XMinorTick','on')
grid on

% Decoder
[D,m] = decoder(x,N);
size(m);

% To append each dialled digit into an array (max 8 numbers)
[handles.data4,handles.data3] = StringNum(handles.data4,D,handles.data3);

% After 8th digit the next number is put into first digit place
if handles.data4 == ' ' 
    handles.data4(handles.data3) = D;
end

% To display the dialled numbers 
set(handles.edit2,'String',handles.data4);         % The dialled number as decoded by the decoder
                                       % is displayed on the edit text

% To plot the output                                       
f = 1 : length(m);
axes(handles.G_output) % Select the proper axes
plot(f,m)
set(handles.G_output,'XMinorTick','on')
grid on
guidata(h,handles);



% --------------------------------------------------------------------
function varargout = pushbutton4_Callback(h, eventdata, handles, varargin)

% To check for N
if handles.chk == 0
    N = 205;
else
    N = handles.data;           %  Number of samples
end

3, Operation results

4, Remarks

Version: 2014a

Topics: MATLAB