finish bluetooth.m; get physLayer stuff

master
Paul Walko 2017-02-28 15:02:32 +00:00
parent aef290e8ee
commit 611d2d5634
10 changed files with 454 additions and 1 deletions

Binary file not shown.

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
octave-workspace

View File

@ -269,7 +269,7 @@ function setPDUField_4()
tS2.payload = cat(2, tS2.advA, tS2.scanRspData); tS2.payload = cat(2, tS2.advA, tS2.scanRspData);
[tS2.advA_hexStr, tS1.advA_hexStr] = mat2hexStr(tS2.advA); [tS2.advA_hexStr, tS1.advA_hexStr] = mat2hexStr(tS2.advA);
[tS2.scanRspData_hexStr, tS1.scapRspData_hexStr] = mat2hexStr(tS2.advscanRspData); [tS2.scanRspData_hexStr, tS1.scapRspData_hexStr] = mat2hexStr(tS2.scanRspData);
payload_struct(1) = tS1; payload_struct(1) = tS1;
payload_struct(2) = tS2 payload_struct(2) = tS2

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,14 @@
% GFSK Parameters (Volume 6, Part A, Section 3.1 of Core_V4.0.pdf)
samp_rate = 2e6;
symb_rate = 1e6;
samps_per_symb = samp_rate/symb_rate;
time_bw_prod = 0.5; % Can vary between 0.45 and 0.55 depending on device.
symb_span = 5;
freq_sep = 360e3;
gauss_taps = gauss_pulse_create(time_bw_prod,symb_span,samps_per_symb);
% Defined Advertising Channel Parameters
adv_preamble = [0,1,0,1,0,1,0,1]; % (Volume 6, Part B, Section 2.1.1 of Core_V4.0.pdf)
adv_accessaddress = [0,1,1,0,1,0,1,1,0,1,1,1,1,1,0,1,1,0,0,1,0,0,0,1,0,1,1,1,0,0,0,1]; % (Volume 6, Part B, Section 2.1.1 of Core_V4.0.pdf)
preamble_proto = conv(fskmod(([adv_preamble,adv_accessaddress]),2,freq_sep,samps_per_symb,samp_rate),gauss_taps);

179
physicalLayer/fskdemod.m Normal file
View File

@ -0,0 +1,179 @@
function z = fskdemod(y,M,freq_sep,nSamp,varargin)
%FSKDEMOD Frequency shift keying demodulation
% Z = FSKDEMOD(Y,M,FREQ_SEP,NSAMP) noncoherently demodulates the complex
% envelope Y of a signal using the frequency shift keying method. M is the
% alphabet size and must be an integer power of 2. FREQ_SEP is the frequency
% separation, and must be positive. NSAMP is the required samples per symbol
% and must be an integer greater than 1. For two dimensional signals, the
% function treats each column of data as one channel.
%
% Z = FSKDEMOD(Y,M,FREQ_SEP,NSAMP,Fs) specifies the sampling frequency (Hz).
% The default sampling frequency is 1.
%
% Z = FSKDEMOD(Y,M,FREQ_SEP,NSAMP,Fs,SYMBOL_ORDER) specifies how the
% function assigns binary words to corresponding integers. If SYMBOL_ORDER
% is set to 'bin' (default), then the function uses a natural binary-coded
% ordering. If SYMBOL_ORDER is set to 'gray', then the function uses a
% Gray-coded ordering.
%
% See also FSKMOD, PSKDEMOD, QAMDEMOD, PAMDEMOD, OQPSKDEMOD.
% Copyright 1996-2012 The MathWorks, Inc.
% Error checks -----------------------------------------------------------------
if (nargin < 4)
error(message('comm:fskdemod:numarg1'));
end
if (nargin > 6)
error(message('comm:fskdemod:numarg2'));
end
% Check that M is a positive integer
if (~isreal(M) || ~isscalar(M) || M<2 || (ceil(M)~=M) || ~isnumeric(M))
error(message('comm:fskdemod:Mreal'));
end
% Check that M is of the form 2^K
if(~isnumeric(M) || ceil(log2(M)) ~= log2(M))
error(message('comm:fskdemod:Mpow2'));
end
% Check that the FREQ_SEP is greater than 0
if( ~isnumeric(freq_sep) || ~isscalar(freq_sep) || freq_sep<=0 )
error(message('comm:fskdemod:freqSep'));
end
% Check that NSAMP is an integer greater than 1
if((~isnumeric(nSamp) || (ceil(nSamp) ~= nSamp)) || (nSamp <= 1))
error(message('comm:fskdemod:nSampPos'));
end
% Check Fs
if (nargin >= 5)
Fs = varargin{1};
if (isempty(Fs))
Fs = 1;
elseif (~isreal(Fs) || ~isscalar(Fs) || ~isnumeric(Fs) || Fs<=0 )
error(message('comm:fskdemod:FsReal'));
end
else
Fs = 1;
end
% Check that the maximum transmitted frequency does not exceed Fs/2
maxFreq = ((M-1)/2) * freq_sep;
if (maxFreq > Fs/2)
error(message('comm:fskdemod:maxFreq'));
end
% Check SYMBOL_ORDER
if(nargin==4 || nargin==5 )
Symbol_Ordering = 'bin'; %default
else
Symbol_Ordering = varargin{2};
if (~ischar(Symbol_Ordering)) || (~strcmpi(Symbol_Ordering,'GRAY')) && (~strcmpi(Symbol_Ordering,'BIN'))
error(message('comm:fskdemod:SymbolOrder'));
end
end
% End of error checks ----------------------------------------------------------
% Assure that Y, if one dimensional, has the correct orientation
wid = size(y,1);
if(wid ==1)
y = y(:);
end
[nRows, nChan] = size(y);
% Preallocate memory
z = zeros(nRows/nSamp, nChan);
% Define the frequencies used for the demodulator.
freqs = (-(M-1)/2 : (M-1)/2) * freq_sep;
% Use the frequencies to generate M complex tones which will be multiplied with
% each received FSK symbol. The tones run down the columns of the "tones"
% matrix.
t = (0 : 1/Fs : nSamp/Fs - 1/Fs)';
phase = 2*pi*t*freqs;
tones = exp(-1i*phase);
% For each FSK channel, multiply the complex received signal with the M complex
% tones. Then perform an integrate and dump over each symbol period, find the
% magnitude, and choose the transmitted symbol corresponding to the maximum
% magnitude.
for iChan = 1 : nChan % loop for each FSK channel
for iSym = 1 : nRows/nSamp
% Load the samples for the current symbol
yTemp = y( (iSym-1)*nSamp+1 : iSym*nSamp, iChan);
% Replicate the received FSK signal to multiply with the M tones
yTemp = yTemp(:, ones(M,1));
% Multiply against the M tones
yTemp = yTemp .* tones;
% Perform the integrate and dump, then get the magnitude. Use a
% subfunction for the integrate and dump, to omit the error checking.
yMag = abs(intanddump(yTemp, nSamp));
% Choose the maximum and assign an integer value to it. Subtract 1 from the
% output of MAX because the integer outputs are zero-based, not one-based.
[~, maxIdx] = max(yMag, [], 2);
z(iSym,iChan) = maxIdx - 1;
end
end
% Restore the output signal to the original orientation
if(wid == 1)
z = z';
end
% Gray decode if necessary
if (strcmpi(Symbol_Ordering,'GRAY'))
[~,gray_map] = gray2bin(z,'fsk',M); % Gray decode
% --- Assure that X, if one dimensional, has the correct orientation --- %
if(size(z,1) == 1)
temp = zeros(size(z));
temp(:) = gray_map(z+1);
z(:) = temp(:);
else
z = gray_map(z+1);
end
end
% EOF -- fskdemod.m
% ------------------------------------------------------------------------------
function y = intanddump(x, Nsamp)
%INTANDDUMP Integrate and dump.
% Y = INTANDDUMP(X, NSAMP) integrates the signal X for 1 symbol period, then
% outputs one value into Y. NSAMP is the number of samples per symbol.
% For two-dimensional signals, the function treats each column as 1
% channel.
%
% --- Assure that X, if one dimensional, has the correct orientation --- %
wid = size(x,1);
if(wid ==1)
x = x(:);
end
[xRow, xCol] = size(x);
x = mean(reshape(x, Nsamp, xRow*xCol/Nsamp), 1);
y = reshape(x, xRow/Nsamp, xCol);
% --- restore the output signal to the original orientation --- %
if(wid == 1)
y = y.';
end
% EOF --- intanddump.m

192
physicalLayer/fskmod.m Normal file
View File

@ -0,0 +1,192 @@
function y = fskmod(x,M,freq_sep,nSamp,varargin)
%FSKMOD Frequency shift keying modulation
% Y = FSKMOD(X,M,FREQ_SEP,NSAMP) outputs the complex envelope of the
% modulation of the message signal X using frequency shift keying modulation. M
% is the alphabet size and must be an integer power of two. The message
% signal must consist of integers between 0 and M-1. FREQ_SEP is the desired
% separation between successive frequencies, in Hz. NSAMP denotes the number
% of samples per symbol and must be an integer greater than 1. For two
% dimensional signals, the function treats each column as one channel.
%
% Y = FSKMOD(X,M,FREQ_SEP,NSAMP,FS) specifies the sampling frequency (Hz).
% The default sampling frequency is 1.
%
% Y = FSKMOD(X,M,FREQ_SEP,NSAMP,FS,PHASE_CONT) specifies the phase continuity
% across FSK symbols. PHASE_CONT can be either 'cont' for continuous phase,
% or 'discont' for discontinuous phase. The default is 'cont'.
%
% Y = FSKMOD(X,M,FREQ_SEP,NSAMP,Fs,PHASE_CONT,SYMBOL_ORDER) specifies how the
% function assigns binary words to corresponding integers. If SYMBOL_ORDER is
% set to 'bin' (default), then the function uses a natural binary-coded
% ordering. If SYMBOL_ORDER is set to 'gray', then the function uses a
% Gray-coded ordering.
%
% See also FSKDEMOD, PSKMOD, QAMMOD, PAMMOD, OQPSKMOD.
% Copyright 1996-2012 The MathWorks, Inc.
% Error checks -----------------------------------------------------------------
if (nargin < 4)
error(message('comm:fskmod:numarg1'));
end
if (nargin > 7)
error(message('comm:fskmod:numarg2'));
end
% Check X
if (~isreal(x) || any(any(ceil(x) ~= x)) || ~isnumeric(x))
error(message('comm:fskmod:xreal1'));
end
% Check that M is a positive integer
if (~isreal(M) || ~isscalar(M) || M<2 || (ceil(M)~=M) || ~isnumeric(M))
error(message('comm:fskmod:Mreal'));
end
% Check that M is of the form 2^K
if(~isnumeric(M) || ceil(log2(M)) ~= log2(M))
error(message('comm:fskmod:Mpow2'));
end
%Check that all X are integers within [0,M-1]
if ((min(min(x)) < 0) || (max(max(x)) > (M-1)))
error(message('comm:fskmod:xreal2'));
end
% Check that the FREQ_SEP is greater than 0
if( ~isnumeric(freq_sep) || ~isscalar(freq_sep) || freq_sep<=0 )
error(message('comm:fskmod:freqSep'));
end
% Check that NSAMP is an integer greater than 1
if((~isnumeric(nSamp) || (ceil(nSamp) ~= nSamp)) || (nSamp <= 1))
error(message('comm:fskmod:nSampPos'));
end
% Check Fs
if (nargin >= 5)
Fs = varargin{1};
if (isempty(Fs))
Fs = 1;
elseif (~isreal(Fs) || ~isscalar(Fs) || ~isnumeric(Fs) || Fs<=0)
error(message('comm:fskmod:FsReal'));
end
else
Fs = 1;
end
samptime = 1/Fs;
% Check that the maximum transmitted frequency does not exceed Fs/2
maxFreq = ((M-1)/2) * freq_sep;
if (maxFreq > Fs/2)
error(message('comm:fskmod:maxFreq'));
end
% Check if the phase is continuous or discontinuous
if (nargin >= 6)
phase_type = varargin{2};
%check the phase_type string
if ~( strcmpi(phase_type,'cont') || strcmpi(phase_type,'discont') )
error(message('comm:fskmod:phaseCont'));
end
else
phase_type = 'cont';
end
if (strcmpi(phase_type, 'cont'))
phase_cont = 1;
else
phase_cont = 0;
end
% Check SYMBOL_ORDER
if(nargin >= 4 && nargin <= 6 )
Symbol_Ordering = 'bin'; % default
else
Symbol_Ordering = varargin{3};
if (~ischar(Symbol_Ordering)) || (~strcmpi(Symbol_Ordering,'GRAY')) && (~strcmpi(Symbol_Ordering,'BIN'))
error(message('comm:fskmod:SymbolOrder'));
end
end
% End of error checks ----------------------------------------------------------
% Assure that X, if one dimensional, has the correct orientation
wid = size(x,1);
if (wid == 1)
x = x(:);
end
% Gray encode if necessary
if (strcmpi(Symbol_Ordering,'GRAY'))
[~,gray_map] = bin2gray(x,'fsk',M); % Gray encode
[~,index]=ismember(x,gray_map);
x=index-1;
end
% Obtain the total number of channels
[nRows, nChan] = size(x);
% Initialize the phase increments and the oscillator phase for modulator with
% discontinuous phase.
phaseIncr = (0:nSamp-1)' * (-(M-1):2:(M-1)) * 2*pi * freq_sep/2 * samptime;
% phIncrSym is the incremental phase over one symbol, across all M tones.
phIncrSym = phaseIncr(end,:);
% phIncrSamp is the incremental phase over one sample, across all M tones.
phIncrSamp = phaseIncr(2,:); % recall that phaseIncr(1,:) = 0
OscPhase = zeros(nChan, M);
% phase = nSamp*# of symbols x # of channels
Phase = zeros(nSamp*nRows, nChan);
% Special case for discontinuous-phase FSK: can use a table look-up for speed
if ( (~phase_cont) && ...
( floor(nSamp*freq_sep/2 * samptime) == nSamp*freq_sep/2 * samptime ) )
exp_phaseIncr = exp(1i*phaseIncr);
y = reshape(exp_phaseIncr(:,x+1),nRows*nSamp,nChan);
else
for iChan = 1:nChan
prevPhase = 0;
for iSym = 1:nRows
% Get the initial phase for the current symbol
if (phase_cont)
ph1 = prevPhase;
else
ph1 = OscPhase(iChan, x(iSym,iChan)+1);
end
% Compute the phase of the current symbol by summing the initial phase
% with the per-symbol phase trajectory associated with the given M-ary
% data element.
Phase(nSamp*(iSym-1)+1:nSamp*iSym,iChan) = ...
ph1*ones(nSamp,1) + phaseIncr(:,x(iSym,iChan)+1);
% Update the oscillator for a modulator with discontinuous phase.
% Calculate the phase modulo 2*pi so that the phase doesn't grow too
% large.
if (~phase_cont)
OscPhase(iChan,:) = ...
rem(OscPhase(iChan,:) + phIncrSym + phIncrSamp, 2*pi);
end
% If in continuous mode, the starting phase for the next symbol is the
% ending phase of the current symbol plus the phase increment over one
% sample.
prevPhase = Phase(nSamp*iSym,iChan) + phIncrSamp(x(iSym,iChan)+1);
end
end
y = exp(1i*Phase);
end
% Restore the output signal to the original orientation
if(wid == 1)
y = y.';
end
% EOF --- fskmod.m

View File

@ -0,0 +1,28 @@
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Purpose: Creates the filter taps for the gaussian pulse shaping
% filter.
%
% Inputs: * bt - time bandwidth product of gaussian pulse
% shape
% * symb_span - pulse overlap (integer number of
% symbols)
% * samps_per_symb - number of samples per symbol
%
% Output: * filt_taps - the filter taps for the created gaussian
% pulse shape
%
% Notes: * Error checking not yet implemented.
%
% Author: William C. Headley
%
% Last Updated: 8/18/2016
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function filt_taps = gauss_pulse_create(bt, symb_span, samps_per_symb)
range = samps_per_symb*symb_span/2;
alpha = sqrt(log(2))/sqrt(2) * (1/bt);
indices = -range:range;
filt_taps = sqrt(pi)/alpha * exp(-(pi/alpha * indices/samps_per_symb).^2);
filt_taps = filt_taps/sum(filt_taps);
end

View File

@ -0,0 +1,39 @@
%
% Copyright 2001 Free Software Foundation, Inc.
%
% This file is part of GNU Radio
%
% GNU Radio 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, or (at your option)
% any later version.
%
% GNU Radio 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 GNU Radio; see the file COPYING. If not, write to
% the Free Software Foundation, Inc., 51 Franklin Street,
% Boston, MA 02110-1301, USA.
%
function v = read_complex_binary (filename, count)
narginchk (1,2);
if (nargin < 2)
count = Inf;
end
f = fopen (filename, 'rb');
if (f < 0)
v = 0;
else
t = fread (f, [2, count], 'float');
fclose (f);
v = t(1,:) + t(2,:)*1i;
[r, c] = size (v);
v = reshape (v, c, r);
end
end