%% 功能：单人呼吸心跳原始数据采集与MATLAB处理
%% 基于平台 IWR1642EVM+DCA1000
%% 思考：如何将IWR1843EVM+DCA1000采集得到的数据移植到这份代码上
%% ========================================================================
clc;clear;close all;
%% =========================================================================
%% 读取数据部分
numADCSamples = 200; % number of ADC samples per chirp
numADCBits = 16;     % number of ADC bits per sample
numRX = 4;           % number of receivers
numLanes = 2;        % do not change. number of lanes is always 2
isReal = 0;          % set to 1 if real only data, 0 if complex data0
chirpLoop = 2;

%% 雷达参数设置
Fs=4e6;             %ADC采样率 见配置说明
c=3*1e8;            %光速
ts=numADCSamples/Fs;%ADC采样时间
slope=70e12;        %调频斜率 
B_valid =ts*slope;  %有效带宽
detaR=c/(2*B_valid);%距离分辨率

%% 读取Bin文件
Filename = 'xxx.bin';  %文件名
fid = fopen(Filename,'r');
adcDataRow = fread(fid, 'int16');
if numADCBits ~= 16
    l_max = 2^(numADCBits-1)-1;
    adcDataRow(adcDataRow > l_max) = adcDataRow(adcDataRow > l_max) - 2^numADCBits;
end
fclose(fid);

fileSize = size(adcDataRow, 1);
PRTnum = fix(fileSize/(numADCSamples*numRX));
fileSize = PRTnum * numADCSamples*numRX;
adcData = adcDataRow(1:fileSize);
% real data reshape, filesize = numADCSamples*numChirps
if isReal
    numChirps = fileSize/numADCSamples/numRX;
    LVDS = zeros(1, fileSize);
    %create column for each chirp
    LVDS = reshape(adcData, numADCSamples*numRX, numChirps);
    %each row is data from one chirp
    LVDS = LVDS.';
else
    numChirps = fileSize/2/numADCSamples/numRX;     %含有实部虚部除以2
    LVDS = zeros(1, fileSize/2);
    %combine real and imaginary part into complex data
    %read in file: 2I is followed by 2Q
    counter = 1;
    for i=1:4:fileSize-1
        LVDS(1,counter) = adcData(i) + sqrt(-1)*adcData(i+2);
        LVDS(1,counter+1) = adcData(i+1)+sqrt(-1)*adcData(i+3); counter = counter + 2;
    end
    % create column for each chirp
    LVDS = reshape(LVDS, numADCSamples*numRX, numChirps);
    %each row is data from one chirp
    LVDS = LVDS.';
end

%% 重组数据
adcData = zeros(numRX,numChirps*numADCSamples);
for row = 1:numRX
    for i = 1:numChirps
        adcData(row, (i-1)*numADCSamples+1:i*numADCSamples) = LVDS(i, (row-1)*numADCSamples+1:row*numADCSamples);
    end
end

retVal= reshape(adcData(1, :), numADCSamples, numChirps); %取第二个接收天线数据，数据存储方式为一个chirp一列

process_adc = retVal(:,1:4:end);

	
%% 距离维FFT（1个chirp)
% figure;
% plot((1:numADCSamples)*detaR,db(abs(fft(process_adc(:,1)))));
% xlabel('距离（m）');
% ylabel('幅度(dB)');
% title('距离维FFT（1个chirp）');
% figure;
% plot(db(abs(fft(process_adc(:,1)))))

%% 相位解缠绕部分
RangFFT = 512;
fft_data_last = zeros(1,RangFFT); 
range_max = 0;
adcdata = process_adc;
numChirps = size(adcdata, 2);

%% 距离维FFT
fft_data = fft(adcdata,RangFFT); 
fft_data = fft_data.';
fft_data_abs = abs(fft_data);
fft_data_abs(:,1:4)=0; %去除直流分量
real_data = real(fft_data);
imag_data = imag(fft_data);


for i = 1:numChirps
    for j = 1:RangFFT  %对每一个距离点取相位 extract phase
        angle_fft(i,j) = atan2(imag_data(i, j),real_data(i, j));
    end
end

% Range-bin tracking 找出能量最大的点，即人体的位置  
for j = 1:RangFFT
    for i = 1:numChirps % 进行非相干积累
        fft_data_last(j) = fft_data_last(j) + fft_data_abs(i,j);
    end
    if ( fft_data_last(j) > range_max)
        range_max = fft_data_last(j);
        max_num = j;
    end
end 

%% 取出能量最大点的相位  extract phase from selected range bin
angle_fft_last = angle_fft(:,max_num);

%% 进行相位解缠  phase unwrapping(手动解)，自动解可以采用MATLAB自带的函数unwrap()
n = 1;
for i = 1+1:numChirps
    diff = angle_fft_last(i) - angle_fft_last(i-1);
    if diff > pi
        angle_fft_last(i:end) = angle_fft_last(i:end) - 2*pi;
        n = n + 1;
    elseif diff < -pi
        angle_fft_last(i:end) = angle_fft_last(i:end) + 2*pi;  
    end
end

%% phase difference 相位差分后的数据
angle_fft_last2=zeros(1,numChirps);
for i = 1:numChirps-1
    angle_fft_last2(i) = angle_fft_last(i+1) - angle_fft_last(i);
    angle_fft_last2(numChirps)=angle_fft_last(numChirps)-angle_fft_last(numChirps-1);
end 

% figure;
% plot(angle_fft_last2);
% xlabel('点数（N）');
% ylabel('相位');
% title('相位差分后的结果');

%%  IIR带通滤波 Bandpass Filter 0.1-0.6hz，得到呼吸的数据
fs =20; %呼吸心跳信号采样率
COE1=chebyshev_IIR; %采用fdatool生成函数
save coe1.mat COE1;
breath_data = filter(COE1,angle_fft_last2); 

% figure;
% plot(breath_data);
% xlabel('时间/点数');
% ylabel('幅度');
% title('呼吸时域波形');

%% 谱估计 -FFT -Peak interval
N1=length(breath_data);
fshift = (-N1/2:N1/2-1)*(fs/N1); % zero-centered frequency
breath_fre = abs(fftshift(fft(breath_data)));              %--FFT
% figure;
% plot(fshift,breath_fre);
% xlabel('频率（f/Hz）');
% ylabel('幅度');
% title('呼吸信号FFT  ');

breath_fre_max = 0; % 呼吸频率

breath_index1 = length(breath_fre)/2;

for i = 1:breath_index1%谱峰最大值搜索 对称其实可以取一半
    if (breath_fre(i) > breath_fre_max)    
        breath_fre_max = breath_fre(i);
        if(breath_fre_max<1e-2) %幅度置信 判断是否是存在人的呼吸
            breath_index=numChirps+1;
        else
            breath_index=i;
        end
    end
end

breath_count =(fs*(breath_index1-breath_index)/numChirps)*60; %呼吸频率解算

%% IIR带通滤波 Bandpass Filter 0.8-2hz 得到心跳的数据
COE2=chebyshev_IIR2;
save coe2.mat COE2;
heart_data = filter(COE2,angle_fft_last2); 

N1=length(heart_data);
fshift = (-N1/2:N1/2-1)*(fs/N1); % zero-centered frequency
heart_fre = abs(fftshift(fft(heart_data))); 
% figure;
% plot(fshift,heart_fre);
% xlabel('频率（f/Hz）');
% ylabel('幅度');
% title('心跳信号FFT');

heart_fre_max = 0; 
heart_index1 = length(heart_fre)/2 ;

for i = 1:heart_index1
    if (heart_fre(i) > heart_fre_max)    
        heart_fre_max = heart_fre(i);
        if(heart_fre_max<1e-2)%幅度置信 判断是否是存在人的心跳
            heart_index=numChirps+1;
        else
            heart_index=i;
        end
    end
end
heart_count =(fs*(heart_index1-(heart_index-1))/numChirps)*60%心跳频率解算

% 2399个帧，约为120s，
% 如果数据长度够长，则雷达会51.2s对呼吸数据和心跳数据进行一次刷新，
%以便实现更为精确的检测。

disp(['呼吸：',num2str(breath_count),'  心跳：',num2str(heart_count)])

%% 动画演示
%读入波形
breath_fre;
heart_fre;
count =0;
%显示波形长度
L =500;
T_frame =0.05 ;%50ms
for i = 1:length(breath_fre)-L-1
    figure(10);
    count=count+i;
    [breath_pks,breath_locs] = findpeaks(breath_data(i:i+L )) ;
    breath_fre =(60/ (L*T_frame))*length(breath_pks);

    [heart_pks,heart_locs] = findpeaks(heart_data(i:i+L )) ;
    heart_fre =(60/ (L*T_frame))*length(heart_pks);

    if count>500
        subplot(121);
        plot((i:i+L)*T_frame,breath_data(i:i+L ),'g');
        grid on
        xlim([i,i+L]*T_frame);
        ylim([-0.8,0.8]);
        hold on
        xlabel('时间（s）');
        ylabel('幅度');
        title(['呼吸时域波形',num2str(breath_fre),'次']);
        hold off
        
        subplot(122);
        plot((i:i+L)*T_frame,heart_data(i:i+L ),'r');
        grid on
        xlim([i,i+L]*T_frame);
        ylim([-0.8,0.8]);
        hold on
        xlabel('时间（s）');
        ylabel('幅度');
        title(['心跳时域波形:',num2str(heart_fre),'次']);
        hold off
    else
    
    %呼吸时域
    subplot(121);
    plot((i:i+L)*T_frame,breath_data(i:i+L ),'g');grid on
    xlim([i,i+L]*T_frame);
    ylim([-0.8,0.8]);
    hold on
    xlabel('时间（s）');
    ylabel('幅度');
    title(['呼吸时域波形:',num2str(breath_fre),'次']);
    hold off

    subplot(122);
    plot((i:i+L)*T_frame,heart_data(i:i+L ),'r');grid on
    xlim([i,i+L]*T_frame);
    ylim([-0.8,0.8]);
    hold on
    xlabel('时间（s）');
    ylabel('幅度');
    title(['心跳时域波形:',num2str(heart_fre),'次']);
    end
    hold off
end


