// ECG_1Dlg.cpp : implementation file
//
#include "stdafx.h"
#include "ECG_1.h"
#include "ECG_1Dlg.h"
#include "MCP3002.h"
#include "DSP_Filter.h"
#include "Ecg_Draw.h"
#include "Statistic_View.h"
#include "ECG_Data.h"
#include "DlgVeloTest.h"
#include "DlgConfirm.h"
#include "DlgPulseMeter.h"
#include "DSP_ECG.h"
#include "Person.h"
#include "Ecg_Info.h"
#include "DlgDSPAll.h"
#include "DlgPersonal.h"
#include "math.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
UINT SmplProcess(LPVOID param)
{
CECG_1Dlg* dlg = (CECG_1Dlg*) param;
int p_DX,p_DY = 0;
CRect rcClient;
CRect Progress;
dlg->GetClientRect(rcClient);
p_DX = 55 + rcClient.Width()/2;
p_DY = 60 + rcClient.bottom/2;
//Move the progres windoe to the center of the dialog
//then recize it to be 300x40 points
Progress.SetRect(p_DX-150,p_DY-20,
p_DX+150,p_DY+20);
dlg->m_ctlSampling.MoveWindow(Progress,TRUE);
dlg->m_ctlSampling.SetPos(0);
for(int i=1;i<21;i++)
{
dlg->m_ctlSampling.SetPos(i);
Sleep(450);
//if start stop is =0 we must stop the procrs control
if(dlg->b_start_stop==0)
{
i=21;
}
}
dlg->m_ctlSampling.MoveWindow(0,0,0,0);
return 0;
}
static void EndSampleNotification(void* obj,unsigned short *ch_0,unsigned short *ch_1,int lenght,CTime start,CTime end);
/////////////////////////////////////////////////////////////////////////////
// CAboutDlg dialog used for App About
class CAboutDlg : public CDialog
{
public:
CAboutDlg();
// Dialog Data
//{{AFX_DATA(CAboutDlg)
enum { IDD = IDD_ABOUTBOX };
//}}AFX_DATA
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CAboutDlg)
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
//}}AFX_VIRTUAL
// Implementation
protected:
//{{AFX_MSG(CAboutDlg)
afx_msg void OnBok();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
};
CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
//{{AFX_DATA_INIT(CAboutDlg)
//}}AFX_DATA_INIT
}
void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAboutDlg)
//}}AFX_DATA_MAP
}
void CAboutDlg::OnBok()
{
// TODO: Add your control notification handler code here
CAboutDlg::OnOK();
}
BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
//{{AFX_MSG_MAP(CAboutDlg)
ON_BN_CLICKED(IDC_BOK, OnBok)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CECG_1Dlg dialog
CECG_1Dlg::CECG_1Dlg(CWnd* pParent /*=NULL*/)
: CDialog(CECG_1Dlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CECG_1Dlg)
m_bmppos = 0;
m_sComment = _T("");
m_b50hz = FALSE;
m_b60hz = FALSE;
m_b40hzlol = FALSE;
m_bw50noht = FALSE;
m_bw45low = FALSE;
m_bw067hz = FALSE;
m_select_segment = -1;
m_srecord = _T("");
//}}AFX_DATA_INIT
// Note that LoadIcon does not require a subsequent DestroyIcon in Win32
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CECG_1Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CECG_1Dlg)
DDX_Control(pDX, IDC_BCORECT, m_ctlcorect);
DDX_Control(pDX, IDC_LDATA, m_ctldata);
DDX_Control(pDX, IDC_BRECORD, m_ctlRecord);
DDX_Control(pDX, IDC_SLIDBMP, m_ctlBmp);
DDX_Control(pDX, IDC_PSAMPLING, m_ctlSampling);
DDX_Slider(pDX, IDC_SLIDBMP, m_bmppos);
DDX_Text(pDX, IDC_ECOMMENT, m_sComment);
DDX_Check(pDX, IDC_C50HZ, m_b50hz);
DDX_Check(pDX, IDC_C60HZ, m_b60hz);
DDX_Check(pDX, IDC_C40LOL, m_b40hzlol);
DDX_Check(pDX, IDC_CW50HZ, m_bw50noht);
DDX_Check(pDX, IDC_CW40HZ, m_bw45low);
DDX_Check(pDX, IDC_CW067, m_bw067hz);
DDX_Radio(pDX, IDC_RADIO1, m_select_segment);
DDX_Text(pDX, IDC_SRECORDS, m_srecord);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CECG_1Dlg, CDialog)
//{{AFX_MSG_MAP(CECG_1Dlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BRECORD, OnBrecord)
ON_WM_HSCROLL()
ON_BN_CLICKED(IDC_BSHOWBMP, OnBshowbmp)
ON_BN_CLICKED(IDC_BTEST, OnBtest)
ON_BN_CLICKED(IDC_BINVERTECG, OnBinvertecg)
ON_BN_CLICKED(IDC_BLOW, OnBlow)
ON_BN_CLICKED(IDC_BUTTON2, OnButton2)
ON_BN_CLICKED(IDC_BPRINT, OnBprint)
ON_BN_CLICKED(IDC_BUTTON1, OnButton1)
ON_BN_CLICKED(IDC_BDELTA, OnBdelta)
ON_BN_CLICKED(IDC_BDELTA2, OnBdelta2)
ON_BN_CLICKED(IDC_BDELTAREVERSE, OnBdeltareverse)
ON_BN_CLICKED(IDC_BUTTON3, OnButton3)
ON_BN_CLICKED(IDC_BDELTAREVERSE2, OnBdeltareverse2)
ON_LBN_SELCHANGE(IDC_LDATA, OnSelchangeLdata)
ON_BN_CLICKED(IDC_BCORECT, OnBcorect)
ON_COMMAND(ID_FILE_EXIT, OnFileExit)
ON_COMMAND(ID_FILE_SAVE, OnFileSave)
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
ON_COMMAND(ID_FILE_NEW, OnFileNew)
ON_COMMAND(ID_INFO_ECG, OnInfoEcg)
ON_COMMAND(ID_INFO_PERSONAL, OnInfoPersonal)
ON_BN_CLICKED(IDC_BSAVEBMP, OnBsavebmp)
ON_COMMAND(ID_INFO_CONFIRM, OnInfoConfirm)
ON_WM_CONTEXTMENU()
ON_BN_CLICKED(IDC_BRECALCALL, OnBrecalcall)
ON_BN_CLICKED(IDC_BEXIT, OnBexit)
ON_COMMAND(ID_HELP_ABOUTECG1, OnHelpAboutecg1)
ON_BN_CLICKED(IDC_BWFLOW, OnBwflow)
ON_BN_CLICKED(IDC_BWFNOHT50HZ, OnBwfnoht50hz)
ON_BN_CLICKED(IDC_BWFLOW40HZ, OnBwflow40hz)
ON_COMMAND(ID_DSP_NOHT50HZ, OnDspNoht50hz)
ON_COMMAND(ID_DSP_LOW100HZ, OnDspLow100hz)
ON_COMMAND(ID_DSP_HIGH0025HZ, OnDspHigh0025hz)
ON_COMMAND(ID_DSP_ECGANALYSIS, OnDspEcganalysis)
ON_COMMAND(ID_DSP_LOW40HZ, OnDspLow40hz)
ON_BN_CLICKED(IDC_BSAVEBMP2, OnBsavebmp2)
ON_BN_CLICKED(IDC_C50HZ, OnC50hz)
ON_BN_CLICKED(IDC_C60HZ, OnC60hz)
ON_BN_CLICKED(IDC_C40LOL, OnC40lol)
ON_BN_CLICKED(IDC_CW50HZ, OnCw50hz)
ON_BN_CLICKED(IDC_CW40HZ, OnCw40hz)
ON_BN_CLICKED(IDC_CW067, OnCw067)
ON_BN_CLICKED(IDC_BAMPL, OnBampl)
ON_BN_CLICKED(IDC_BDSPALL, OnBdspall)
ON_BN_CLICKED(IDC_RADIO1, OnRadio1)
ON_WM_LBUTTONDBLCLK()
ON_WM_RBUTTONDOWN()
ON_COMMAND(ID_ECGINFO_PERSONAL, OnInfoPersonal)
ON_BN_CLICKED(IDC_RADIO2, OnRadio1)
ON_BN_CLICKED(IDC_RADIO3, OnRadio1)
ON_BN_CLICKED(IDC_RADIO4, OnRadio1)
ON_BN_CLICKED(IDC_BECGPRINT, OnBecgprint)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CECG_1Dlg message handlers
BOOL CECG_1Dlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Add "About..." menu item to system menu.
// IDM_ABOUTBOX must be in the system command range.
ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
ASSERT(IDM_ABOUTBOX < 0xF000);
CMenu* pSysMenu = GetSystemMenu(FALSE);
if (pSysMenu != NULL)
{
CString strAboutMenu;
strAboutMenu.LoadString(IDS_ABOUTBOX);
if (!strAboutMenu.IsEmpty())
{
pSysMenu->AppendMenu(MF_SEPARATOR);
pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
}
}
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
//Make dlg_pulse_meter modless
dlg_pulse_meter.Create(IDD_DPULSEMETER,this);
//set bool variable to show our program that dlg_pulse_meter is closed
b_dlgPulseMeter = 0;
//
dlg_pulse_meter.s_CurrPulse = "0";
dlg_pulse_meter.s_PastPulse = "0";
//Calculate win-syncc filter kernels
//for sampling rate 500hz
dsp_flf.LoadFilterKernels(500);
i_fsmpl = 500;
//////////////////////////////
m_select_segment = 3;
//Sets the filter defaut
m_b50hz=1;
m_b40hzlol=1;
s_filter_input = "";
//Set BMP view type to view ECG records
i_bmp = 0;
m_ctlSampling.SetRange(0,20);
m_ctlBmp.SetRange(0,4);
s_ECG_Info = "QRS ?";
i_old_ctldata_index = 0;
GetDlgItem(IDC_BCORECT)->EnableWindow(FALSE);
//set the start stop variable to be stopped
b_start_stop = 0;
//Set the QRS measurement variables
i_QRS_count=0;
i_QRS_ms=0;
i_PR_ms=0;
i_QT_QTc_ms=0;
hh = 0;
mm = 0;
//Must be done this initialization
TStart = 0;
///////////////////////////////////
ZeroArr(AR_ECG,5000);
ZeroArr(AR_REV,5000);
m_sComment = "";
//Unvisible sampling process control
m_ctlSampling.MoveWindow(0,0,0,0);
UpdateData(false);
return TRUE; // return TRUE unless you set the focus to a control
}
void CECG_1Dlg::OnSysCommand(UINT nID, LPARAM lParam)
{
if ((nID & 0xFFF0) == IDM_ABOUTBOX)
{
CAboutDlg dlgAbout;
dlgAbout.DoModal();
}
else
{
CDialog::OnSysCommand(nID, lParam);
}
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CECG_1Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialog::OnPaint();
//redraw BMP with ECG
if(i_bmp==0)
OnButton1();
//else draw statistical info
if(i_bmp==1)
OnButton3();
}
}
// The system calls this to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CECG_1Dlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}
void CECG_1Dlg::OnBrecord()
{
// TODO: Add your control notification handler code here
//Before starting sampling deletes previous AR_ECG and AR__REV
//function is stopped
UpdateData(true);
if(b_start_stop == 0)
{
//Open dialog to show measured pulse
ShowPulseDialog();
//Start sampling process
StartSampling();
}
//function is active
else
{
StopSampling();
//close pulse dialog if it was created
HidePulseDialog();
}
}
void EndSampleNotification(void* obj,unsigned short *ch_0,unsigned short *ch_1,int lenght,CTime start,CTime end)
{
CECG_1Dlg* dlg = (CECG_1Dlg*) obj;
dlg->TStart = start;
dlg->s_ECG_Info.Format("%d:%d",start.GetHour(),
start.GetMinute());
dlg->hh = start.GetHour();
dlg->mm = start.GetMinute();
//filtering and copying
dlg->CopyFromSample(ch_0,ch_1,lenght);
//First we need to copy sampled arrays in to a program arrays
//if start stop flag is =1 then after conversion set window text
//to show that we can make a new conversion
if(dlg->b_start_stop == 1)
{
//Copy sampled data in to the ECG_DATA class
dlg->SetData(dlg->AR_ECG,2500);
dlg->m_ctldata.AddString(dlg->s_ECG_Info);
//Show pulse on pulse meter dialog
dlg->ShowCurrPulse(dlg->m_ctldata.GetCount());
dlg->StartSampling();
}
if(dlg->b_start_stop == 0)
{
// dlg->b_start_stop = 0;
dlg->m_ctlRecord.SetWindowText("Star Record");
dlg->m_ctldata.AddString(dlg->s_ECG_Info);
}
}
void CECG_1Dlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
UpdateData(true);
OnButton1();
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CECG_1Dlg::CopyFromSample(unsigned short *ar0, unsigned short *ar1, int lenght)
{
//memmove does not work!!!
for(int i=0;i<lenght;i++)
{
AR_ECG[i] = double(*(ar0+i));
AR_REV[i] = double(*(ar1+i));
}
//Calculate the signal mean
//Normalize array
dsp_flf.SetArrToNormalize(&AR_ECG[0],lenght);
dsp_flf.SetArrToNormalize(&AR_REV[0],lenght);
//Low filtr
// dsp_flf.Filter_High(AR_ECG,AR_ECG,5000,1,500,0.000001);
//If noht filter was selected use it 2 times
s_filter_input = "";
if(m_b50hz==1)
{
dsp_flf.RFilter_Noht(&AR_ECG[0],lenght,500,50,0.005);
dsp_flf.RFilter_Noht(&AR_ECG[0],lenght,500,50,0.005);
s_filter_input = s_filter_input + " 2x50Hz Rnoht/";
}
//if noht filter was selected use it 2 times
if(m_b60hz==1)
{
dsp_flf.RFilter_Noht(&AR_ECG[0],lenght,500,60,0.01);
dsp_flf.RFilter_Noht(&AR_ECG[0],lenght,500,60,0.01);
s_filter_input = s_filter_input + " 2x60Hz Rnoht/";
}
//If lol filter was selected use it
if(m_b40hzlol==1)
{
dsp_flf.RFilter_Low(&AR_ECG[0],lenght,500,0.51);
s_filter_input = s_filter_input + " 1x40Hz Rlow/";
}
if(m_bw45low==1)
{
dsp_flf.WFilter_Low40Hz(AR_ECG,AR_ECG,lenght,500,40);
// dsp_flf.WFilter_Low40Hz(AR_ECG,AR_ECG,lenght,500,40);
s_filter_input = s_filter_input + " 1x40Hz Wlol/";
}
if(m_bw50noht==1)
{
dsp_flf.WFilter_Noht(AR_ECG,AR_ECG,lenght,500,50);
dsp_flf.WFilter_Noht(AR_ECG,AR_ECG,lenght,500,50);
s_filter_input = s_filter_input + " 2x50Hz Wnoht/";
}
if(m_bw067hz==1)
{
dsp_flf.WFilter_High(&AR_ECG[0],&AR_ECG[0],
5000,-1,500,0.0001);
s_filter_input = s_filter_input + " 1x>0.67Hz Whigh/";
}
if(s_filter_input=="")
s_filter_input = " NO FILTER";
//Resample signal from500Hz to 250Hz
int k = Resample(&AR_ECG[0],&AR_ECG[0],lenght,500,250);
//After this we can draw a bitmap with sampled arrays
OnBtest();
}
void CECG_1Dlg::OnOK()
{
// TODO: Add extra validation here
}
void CECG_1Dlg::OnBshowbmp()
{
// TODO: Add your control notification handler code here
// dsp_flf.Filter_Low(&AR_ECG[0],5000,500,0.05);
dsp_flf.SetArrToNormalize(&AR_ECG[0],5000);
dsp_flf.RFilter_Noht(&AR_ECG[0],5000,250,50,0.017);
OnBtest();
}
int CECG_1Dlg::Resample(double *dest, double *source, int lenght, int fold, int fnew)
{
int k;
k = fold/fnew;
for(int i=0;i<lenght/k;i++)
{
*(dest+i) = *(source+i*k);
}
//Zero end of the array
for(i=lenght/k;i<lenght;i++)
{
*(dest+i) = 0;
}
return k;
}
void CECG_1Dlg::SamplingProcess()
{
//Begins a new thread to visualize sampling process
AfxBeginThread(SmplProcess,this);
SetThreadPriority(SmplProcess,THREAD_PRIORITY_NORMAL);
}
void CECG_1Dlg::OnBtest()
{
//Pass curr record throught the ECG_DSP
dsp_ecg.SetECG(AR_ECG,2500,AR_REV,&i_QRS_count,&i_QRS_ms,
&i_PR_ms,&i_QT_QTc_ms,m_select_segment);
//Format the ECG record intervals info
s_ECG_Info.Format("%d:%d Pulse-rate %d/min, QRSint.%dms, PRint.%dms, QTint.%dms",
hh,mm,i_QRS_count,i_QRS_ms,i_PR_ms,i_QT_QTc_ms);
OnButton1();
}
void CECG_1Dlg::OnBinvertecg()
{
// TODO: Add your control notification handler code here
//Inverst the array ECG
dsp_flf.InvertArr(&AR_ECG[0],&AR_ECG[0],5000);
//Inverts the array REV
dsp_flf.InvertArr(&AR_REV[0],&AR_REV[0],5000);
OnBtest() ;
}
int CECG_1Dlg::CountQRS(double *ECG, int lenght)
{
int D = 0;
/* int Delta[5000];
int Deltamin[5000];
for(int i=0;i<lenght;i++)
{
*(AR_REV+i) = 0;
Deltamin[i]= 0;
}
for(i=0;i<lenght-1;i++)
{
D = int(*(ECG+i+1) - *(ECG+i));
Delta[i] = D;
if(D>16)
*(AR_REV+i) = 2;
if(D<-16)
*(AR_REV+i) = -2;
}
D = 0;
int d_count;
for(i=0;i<lenght-1;i++)
{
d_count=0;
if(*(AR_REV+i)==2)
{ //*(AR_REV+i-1)=400;//find the delta begining
do{ i++;d_count++;}
while(*(AR_REV+i)==2);
int max=i;
do{max++;}
while(*(AR_REV+max)==2);
*(AR_REV+max) = *(AR_ECG+max);//fing max after delta+
do{max++;}
while(*(AR_REV+max)<0);
*(AR_REV+max+1) = *(AR_ECG+max);//find min after max
max = i;
do{max--;}
while(Delta[max]>0);
*(AR_REV+max+2) = *(ECG+max+1);//find min after d-
if(d_count>2)
{D++;
//*(AR_REV+i) = 400;//end of the delta+
}
}
}
//D contains QRS/10s to convert it in QRS/min
//we must multiply it by 6, because 1 min contains 60 seconds
i_QRS_count = D*6;
//Format the QRS count in to text string
s_ECG_Info.Format("%d:%d QRS %d/min",hh,mm,i_QRS_count);
*/ return D;
}
void CECG_1Dlg::OnBlow()
{
// TODO: Add your control notification handler code here
dsp_flf.RFilter_Low(&AR_ECG[0],5000,250,0.62);
OnBtest();
}
void CECG_1Dlg::OnButton2()
{
// TODO: Add your control notification handler code here
dsp_flf.WFilter_High(&AR_ECG[0],&AR_ECG[0],
5000,-1,250,0.0001);//255Hz*0.001 = 0.225
OnBtest() ;
}
void CECG_1Dlg::OnBprint()
{
// TODO: Add your control notification handler code here
CPrintDialog dlgPrint(FALSE,PD_ALLPAGES ,this);
if(dlgPrint.DoModal()==IDOK)
{
CDC dcPrint;
dcPrint.Attach(dlgPrint.GetPrinterDC());
// dcPrint.SetMapMode(MM_LOMETRIC);
DOCINFO myPrintJob;
myPrintJob.cbSize = sizeof(myPrintJob);
myPrintJob.lpszDocName = "MyPrintJob";
myPrintJob.lpszOutput = NULL;
myPrintJob.lpszDatatype = NULL;
myPrintJob.fwType = NULL;
if(dcPrint.StartDoc(&myPrintJob)>=0)
{
dcPrint.StartPage();
CString str;
for(int i=1;i<10;i++)
{
str.Format("points %d lenght",100*i);
dcPrint.MoveTo(10,100*i);
dcPrint.TextOut(10,100*i,str);
dcPrint.LineTo(100*i,100*i);
}
dcPrint.MoveTo(100,100);
dcPrint.LineTo(1000,100);
dcPrint.EndPage();
dcPrint.EndDoc();
}
dcPrint.DeleteDC();
}
}
void CECG_1Dlg::OnButton1()
{
// TODO: Add your control notification handler code here
i_bmp = 0;
CRect rcClient;
GetClientRect(rcClient);
CClientDC dc(this);
int x,y;
y = 100;
x = 220;
rcClient.SetRect(x,y,x+500,y+500);
ecg_draw.SetArr(&AR_ECG[0],&AR_REV[0],5000);
ecg_draw.SetEcgInfo(s_ECG_Info);
ecg_draw.SetEcgDrawRect(&dc,rcClient,m_bmppos*500,m_bmppos*500+500);
//Set the redraw type to be bmp_ecg
if(i_bmp==1)
i_bmp = 0;
}
void CECG_1Dlg::OnBdelta()
{
// TODO: Add your control notification handler code here
dsp_flf.RFilter_Low(AR_ECG,5000,250,0.1);
dsp_flf.Delta1(AR_REV,AR_ECG,5000);
OnButton1();
}
void CECG_1Dlg::OnBdelta2()
{
// TODO: Add your control notification handler code here
dsp_flf.RFilter_Low(AR_ECG,5000,250,0.1);
dsp_flf.Delta2(AR_REV,AR_ECG,5000);
OnButton1();
}
void CECG_1Dlg::OnBdeltareverse()
{
// TODO: Add your control notification handler code here
dsp_flf.DeltaReverse1(AR_REV,AR_REV,5000);
OnButton1();
}
void CECG_1Dlg::StartSampling()
{
cur_index=0;
//Starts the sampling process
//before this format the date
SetTestdate();
m_ctlRecord.SetWindowText("End Record");
mcp3002.SetEndSampleNotification(this,EndSampleNotification);
//Loads filter kernels for 500Hz
dsp_flf.LoadFilterKernels(500);
mcp3002.MMT_Start(0x378);
//Visualize process with time bar
SamplingProcess();
b_start_stop = 1;
}
void CECG_1Dlg::StopSampling()
{
//End the sampling process
mcp3002.MMT_Stop();
m_ctlRecord.SetWindowText("Star Record");
//Loads filter kernels for 250Hz
dsp_flf.LoadFilterKernels(250);
b_start_stop = 0;
// GetDlgItem(IDC_BRECORD)->EnableWindow(false);
}
void CECG_1Dlg::OnButton3()
{
// TODO: Add your control notification handler code here
//Set the redraw type to be bmp_statistic
if(i_bmp==0)
i_bmp = 1;
//Count all qrs min
CountQRSmin();
// CountAllQRS();
// dsp_flf.Message(QRS_MIN_COUNT.GetSize());
CRect rcClient;
GetClientRect(rcClient);
CClientDC dc(this);
int x,y;
y = 100;
x = 220;
double Qrscount[2500];
double pwt[2500];
for(int i=0;i<2500;i++)
{
Qrscount[i]=1;
pwt[i]=10;
}
for(i=0;i<QRS_MIN_COUNT.GetSize();i++)
{
Qrscount[i] = QRS_MIN_COUNT.GetAt(i);
pwt[i] = Qrscount[i] * 2 + rand()%50 - rand()%50;
//pwt[i] = 100;//
}
dsp_flf.RFilter_Low(pwt,1000,100,0.45);
// dsp_flf.Message(i);//OK
rcClient.SetRect(x,y,x+500,y+200);
statistic_draw.SetArr(Qrscount,pwt,2500);
CString str;
str = " (Y=pulse & power rates, X=minutes)";
str = "Test date "+
ecg_data.ecg_info.velo_test_date.Format("%Y-%mm-%dd Start at %H:%M")+
str;
statistic_draw.SetInfo(str);
statistic_draw.SetEcgDrawRect(&dc,rcClient,m_bmppos*500,m_bmppos*500+500);
}
void CECG_1Dlg::OnBdeltareverse2()
{
// TODO: Add your control notification handler code here
dsp_flf.DeltaReverse2(AR_REV,AR_REV,5000);
OnButton1();
}
void CECG_1Dlg::SetData(double *source, int lenght)
{
//Adds new portion of sampled data to the ECG_DATA DATA
//word array
m_sComment = "Used filters:"+ s_filter_input;
ecg_data.SetDataNew(source,lenght,m_sComment,i_QRS_count,
i_QRS_ms,i_PR_ms,i_QT_QTc_ms,hh,mm);
}
void CECG_1Dlg::OnSelchangeLdata()
{
// TODO: Add your control notification handler code here
int index = m_ctldata.GetCurSel();
//If there are something in the list box
//enable corect button
if(index>=0)
{
GetDlgItem(IDC_BCORECT)->EnableWindow(TRUE);
i_old_ctldata_index = index;
m_srecord.Format("Record %d of %d",index,m_ctldata.GetCount()-1);
UpdateData(false);
GetDataFrom(AR_ECG,index,2500);
dsp_flf.SetArrToNormalize(AR_ECG,2500);
OnBtest();
}
}
void CECG_1Dlg::GetDataFrom(double *dest,int start, int lenght)
{
UpdateData(true);
ecg_data.GetFrom(dest,start*lenght,lenght);
//Gets the info about the recorded segment
//GetInfoFrom returns the CString comment about the segment
m_sComment = ecg_data.GetInfoFrom(start,&i_QRS_count,
&i_QRS_ms,&i_PR_ms,&i_QT_QTc_ms,&hh,&mm);
i_QRS_count = ecg_data.GetQRSCount(start);
s_ECG_Info.Format("%d:%d QRS %d /m",hh,mm,i_QRS_count);
UpdateData(false);
}
void CECG_1Dlg::SetDataAt(double* source,int start,int lenght)
{
UpdateData(true);
ecg_data.SetDataAt(source,start*lenght,lenght);
//Sets the info about the ECG segment
ecg_data.SetInfoAt(start,m_sComment,i_QRS_count,
i_QRS_ms,i_PR_ms,i_QT_QTc_ms,hh,mm);
UpdateData(false);
}
void CECG_1Dlg::OnBcorect()
{
// TODO: Add your control notification handler code here
//This function sets data in to ecg_data class
SetDataAt(AR_ECG,i_old_ctldata_index,2500);
//Disable control correct, because the correction was done
GetDlgItem(IDC_BCORECT)->EnableWindow(FALSE);
//Gets the selected index string
ecg_data.GetInfoFrom(i_old_ctldata_index,&i_QRS_count,&i_QRS_ms,
&i_PR_ms,&i_QT_QTc_ms,&hh,&mm);
CString str;
str.Format("%d:%d %d�/���",hh,mm,i_QRS_count);
//delete the selected string
m_ctldata.DeleteString(i_old_ctldata_index);
//insert new value at his position
m_ctldata.InsertString(i_old_ctldata_index,str);
//after this remember the last selection
m_ctldata.SetCurSel(i_old_ctldata_index);
}
void CECG_1Dlg::OnFileExit()
{
// TODO: Add your command handler code here
OnBexit();
}
void CECG_1Dlg::OnFileSave()
{
// TODO: Add your command handler code here
//If sampling is active stop it now!
StopSampling();
//close pulse dialog if it is neaded
HidePulseDialog();
//Load variables to dlg_personal
SetPersonal();
//Opens the personal info dlg to confirm before saving
int result = dlg_personal.DoModal();
if(result == IDOK)
{//If the info was confirmed read
//confirmed info from dlg_personal
//and set it in to ecg_data.personal
GetPersonal();
CString FileName;
CFileDialog m_lFile(FALSE);
m_lFile.m_ofn.lpstrFilter = "ECG\0*.ecg";
m_lFile.m_ofn.lpstrDefExt = ".ecg";
if(m_lFile.DoModal()==IDOK)
{
FileName = m_lFile.GetFileName();
ecg_data.SaveData(FileName);
}
}
}
void CECG_1Dlg::OnFileOpen()
{
// TODO: Add your command handler code here
//If sampling is active stop it now!
StopSampling();
CString FileName;
CFileDialog m_lFile(TRUE);
m_lFile.m_ofn.lpstrFilter = "ECG\0*.ecg";
m_lFile.m_ofn.lpstrDefExt = ".ecg";
if(m_lFile.DoModal()==IDOK)
{
FileName = m_lFile.GetFileName();
ecg_data.OpenFile(FileName);
//Confirm personal information
SetPersonal();
//open the dialog with personal data
int result = dlg_personal.DoModal();
//If dialog was closed
if(result == IDOK)
{
//read confirmed data and set it to ecg_data.person
GetPersonal();
//Full the list box with a new values
OnBrecalcall();
dsp_flf.LoadFilterKernels(250);
// char title[30];
// CECG_1Dlg::GetWindowText(title,30);
// CString sTitle = LPCSTR(title);
CECG_1Dlg::SetWindowText("ECG_1 Test Version File: "+FileName);
// EnableControls();
}
}
}
void CECG_1Dlg::OnFileNew()
{
//Stop sampling
StopSampling();
//close pulse dialog if it is neaded
HidePulseDialog();
//Clear person values
ClearPersonal();
//clear ECG info section
ClearECGInfo();
// TODO: Add your command handler code here
int result = dlg_personal.DoModal();
if(result==IDOK)
{
GetPersonal();
NewECG();
//Reload filter kernels for sampling rate 500Hz
dsp_flf.LoadFilterKernels(500);
}
}
void CECG_1Dlg::NewECG()
{
//Stops the sampling process
StopSampling();
//Clear ecg_data arrays
ecg_data.RemoveAll();
m_ctldata.ResetContent();
s_ECG_Info = "?";
//Clear the AR_ECG
ZeroArr(AR_ECG,5000);
ZeroArr(AR_REV,5000);
//Do new drawing and calculations
OnBtest();
}
void CECG_1Dlg::ZeroArr(double *dest, int lenght)
{
for(int i=0;i<lenght;i++)
{
*(dest+i) = 0;
}
}
void CECG_1Dlg::CountQRSmin()
{
int min_count = 0;
if(QRS_MIN_COUNT.GetSize()>0)
QRS_MIN_COUNT.RemoveAll();
int lenght = ecg_data.TIME.GetSize();
// dsp_flf.Message(lenght);//OK
if(lenght>0)
{
CWordArray min;
CWordArray qrs_c;
BYTE h,m=0;
//Copy all QRS_counts in to rate_min
for(int i=0;i<lenght;i++)
{
ecg_data.GetPosTime(i,&h,&m);
min.Add(m);
qrs_c.Add(ecg_data.GetQRSCount(i));
}
BYTE m_old;
int count = 0;
double mean=0;
int pos=0;
i=0;
int corect=0;
do
{
count=0;
mean=0;
m_old=min.GetAt(pos);
// dsp_flf.Message(m_old);
do
{
mean = mean + qrs_c.GetAt(i);
i++;
count++;
if(i>=min.GetSize())
corect=-1;
}
while((m_old == min.GetAt(i+corect))&(i<min.GetSize()));
// dsp_flf.Message(i-pos);
mean = mean/count;
// dsp_flf.Message(mean);
QRS_MIN_COUNT.Add(int(mean));
pos = i;//
}
while(pos<min.GetSize());
}
}
void CECG_1Dlg::GetPersonal()
{
//reads the personel data from dlg_personal
//and set it in to the ecg_data.person
ecg_data.person.sEGN = dlg_personal.m_sEGN;
ecg_data.person.Birth_Date = dlg_personal.m_birthdate;
ecg_data.person.sName_1 = dlg_personal.m_sName1;
ecg_data.person.sName_2 = dlg_personal.m_sName2;
ecg_data.person.sName_3 = dlg_personal.m_sName3;
ecg_data.person.Sex = dlg_personal.m_sSex;
ecg_data.person.sAddress = dlg_personal.m_sAddress;
ecg_data.person.sPhone = dlg_personal.m_sPhone;
}
void CECG_1Dlg::SetPersonal()
{
//get the data from ecg_data.person
//and set it in to the dlg_personal variables
//to lett the user confirm it
dlg_personal.m_sEGN = ecg_data.person.sEGN;
//if birthdate == 0 set it to some value
if(ecg_data.person.Birth_Date == 0)
ecg_data.person.Birth_Date.SetDate(2000,01,01);
dlg_personal.m_birthdate = ecg_data.person.Birth_Date;
dlg_personal.m_sName1 = ecg_data.person.sName_1;
dlg_personal.m_sName2 = ecg_data.person.sName_2;
dlg_personal.m_sName3 = ecg_data.person.sName_3;
dlg_personal.m_sSex = ecg_data.person.Sex;
dlg_personal.m_sAddress = ecg_data.person.sAddress;
dlg_personal.m_sPhone = ecg_data.person.sPhone ;
}
void CECG_1Dlg::ClearPersonal()
{
dlg_personal.m_sEGN = "";
dlg_personal.m_birthdate.SetDate(2000,01,01);
dlg_personal.m_sName1 = "";
dlg_personal.m_sName2 = "";
dlg_personal.m_sName3 = "";
dlg_personal.m_sSex = "";
dlg_personal.m_sAddress = "";
dlg_personal.m_sPhone = "" ;
}
void CECG_1Dlg::OnInfoEcg()
{
// TODO: Add your command handler code here
//open a ECG statistical info dialog
//calculate statistic meandevmaxmin
ECG_Statistic();
//Format the CString variables at velo_test dialog
FormatTestDlg();
////////////////////////////
//open dialog
int result = dlg_velo_test.DoModal();
if(result == IDOK)
{
//Update the velo test info
//Because we have no sensors for blood preasure put the values handly
//temperature too
ecg_data.ecg_info.BloodPreasure.iMean =
atoi(dlg_velo_test.m_sbloodpreaure);
ecg_data.ecg_info.Temperature.iMean =
atoi(dlg_velo_test.m_stemperature);
}
}
void CECG_1Dlg::OnInfoPersonal()
{
// TODO: Add your command handler code here
//Wieu the personal information to confirm
SetPersonal();
int result = dlg_personal.DoModal();
if(result == IDOK)
{
//Update the personal info
GetPersonal();
}
}
int CECG_1Dlg::GetQRSmean()
{
CWordArray QRScount;
//Counts the mean QRS for all records
double count = 0;
int lenght = ecg_data.GetAllDataLenght()/2500;
for(int i=0;i<lenght;i++)
{
QRScount.Add(ecg_data.GetQRSCount(i));
}
//calculate the mean
for(i=0;i<lenght;i++)
{
count = count + QRScount.GetAt(i);
}
count = count/lenght;
QRScount.RemoveAll();
// dsp_flf.Message(count);
return int(count);
}
void CECG_1Dlg::SetTestdate()
{
//Sets current date when starts the measurement
//if this is old measurement we do not need to set date
if(ecg_data.ecg_info.velo_test_date==0)
{
//if tere are no any date set it
ecg_data.ecg_info.velo_test_date=
COleDateTime::GetCurrentTime();
}
}
void CECG_1Dlg::OnBsavebmp()
{
// TODO: Add your control notification handler code here
if(ecg_data.GetAllDataLenght()/2500>0)
{
//Set personal info for print form
CPerson* lpPerson;
lpPerson = &ecg_data.person;
CEcg_Info* lpEcg_Info;
lpEcg_Info = &ecg_data.ecg_info;
ecg_draw.PrintBMP(lpPerson);
}
}
void CECG_1Dlg::OnInfoConfirm()
{
// TODO: Add your command handler code here
//Check for data in ecg_info section
if(ecg_data.ecg_info.Confirm_By=="")
//if there are no any name set something
ecg_data.ecg_info.Confirm_By = "NO NAME";
if(ecg_data.ecg_info.Conclusion=="")
//if there are no conclusion set something
ecg_data.ecg_info.Conclusion = "NOT CONFIRMED";
//set dlg_confirm variables
dlg_confirm.m_sName = ecg_data.ecg_info.Confirm_By;
dlg_confirm.m_sConclusion = ecg_data.ecg_info.Conclusion;
if(dlg_confirm.DoModal()==IDOK)
{
//read the values about name and conclusion
ecg_data.ecg_info.Confirm_By = dlg_confirm.m_sName;
ecg_data.ecg_info.Conclusion = dlg_confirm.m_sConclusion;
}
}
void CECG_1Dlg::ClearECGInfo()
{
//Clear section of data.ecg_info
ecg_data.ecg_info.Confirm_By = "";
ecg_data.ecg_info.Conclusion = "";
//Clear all ecg_info
}
void CECG_1Dlg::OnContextMenu(CWnd* pWnd, CPoint point)
{
// TODO: Add your message handler code here
CMenu menu;
menu.LoadMenu(IDR_CONTEXTMENU);
CRect rect;
m_ctldata.GetWindowRect(rect);
int x = point.x;
int y = point.y;
//if mouse is on m_ctldata rect
if(x>rect.left&x<rect.right&y>rect.top&y<rect.bottom)
{
CMenu* pContextMenu = menu.GetSubMenu(0);
pContextMenu->TrackPopupMenu(TPM_CENTERALIGN+
TPM_LEFTBUTTON,
point.x,point.y,pWnd,NULL);
}
//if mous is on BMP rect
if(x>251&x<750&y>196&y<449)
{
CMenu* pContextMenu = menu.GetSubMenu(1);
pContextMenu->TrackPopupMenu(TPM_CENTERALIGN+
TPM_LEFTBUTTON,
point.x,point.y,pWnd,NULL);
}
}
void CECG_1Dlg::OnBrecalcall()
{
// TODO: Add your control notification handler code here
//This function recalculates all ECG data segment
//to find the QRS count
int count = ecg_data.GetAllDataLenght()/2500;
if(count>0)
{
CString str;
//because we will recalculate all data
//we can remove it
m_ctldata.ResetContent();
for(int i=0;i<count;i++)
{
//reads data from i*2500 to i*2500+2500
// GetDataFrom(AR_ECG,i,2500);
ecg_data.GetInfoFrom(i,&i_QRS_count,&i_QRS_ms,
&i_PR_ms,&i_QT_QTc_ms,&hh,&mm);
//normalize array because it need or may be not normalized
// dsp_flf.SetArrToNormalize(AR_ECG,2500);
//detect QRS
//CountQRS(AR_ECG,2500);
// dsp_ecg.SetECG(AR_ECG,2500,AR_REV,&i_QRS_count,
// &i_QRS_ms,&i_PR_ms,&i_QT_QTc_ms);
// ecg_data.SetInfoAt(i,m_sComment,i_QRS_count,i_QRS_ms,
// i_PR_ms,i_QT_QTc_ms,hh,mm);
//Format a string to be fitt in m_ctldata control
str.Format("%d:%d %d�/���",hh,mm,i_QRS_count);
//inserts a string at current position
m_ctldata.InsertString(i,str);
}
}
OnBtest();
}
void CECG_1Dlg::OnBexit()
{
// TODO: Add your control notification handler code here
mcp3002.MMT_Stop();
Sleep(10);
//close pulse dialog if it is neaded
HidePulseDialog();
//Close the main program dialog
CDialog::OnOK();
}
void CECG_1Dlg::OnHelpAboutecg1()
{
// TODO: Add your command handler code here
CAboutDlg dlg;
dlg.DoModal();
}
void CECG_1Dlg::OnBwflow()
{
// TODO: Add your control notification handler code here
//window-cync filter low<100Hz
dsp_flf.WFilter_Low100Hz(AR_ECG,AR_ECG,2500,250,100);
OnBtest();
}
void CECG_1Dlg::OnBwfnoht50hz()
{
// TODO: Add your control notification handler code here
//window-cync filter noht <47Hz >53Hz
dsp_flf.WFilter_Noht(AR_ECG,AR_ECG,2500,250,50);
OnBtest();
}
void CECG_1Dlg::OnBwflow40hz()
{
// TODO: Add your control notification handler code here
//window-cync filter low<40Hz
dsp_flf.WFilter_Low40Hz(AR_ECG,AR_ECG,2500,250,40);
OnBtest();
}
void CECG_1Dlg::OnDspNoht50hz()
{
// TODO: Add your command handler code here
OnBwfnoht50hz();
}
void CECG_1Dlg::OnDspLow100hz()
{
// TODO: Add your command handler code here
OnBwflow();
}
void CECG_1Dlg::OnDspHigh0025hz()
{
// TODO: Add your command handler code here
OnButton2();
}
void CECG_1Dlg::OnDspEcganalysis()
{
// TODO: Add your command handler code here
}
void CECG_1Dlg::OnDspLow40hz()
{
// TODO: Add your command handler code here
OnBwflow40hz();
}
void CECG_1Dlg::ECG_Statistic()
{
int mean,dev,max,min=0;
double* arr;
int lenght = ecg_data.QRS_COUNT.GetSize();
if(lenght>0)
{
arr = new double [lenght];
// dsp_flf.Message(lenght); //test
//Start calculating ecg statistic
//QRS
for(int i=0;i<lenght;i++)
{
//read qrs info and set it in arr
*(arr+i) = ecg_data.GetQRSCount(i);
}
//calculate meandevmaxmin
ecg_data.ecg_info.HeartRate.iMean =
dsp_flf.Mean(arr,lenght);
ecg_data.ecg_info.HeartRate.iDev =
dsp_flf.StandardDeviation(arr,lenght);
ecg_data.ecg_info.HeartRate.iMax =
dsp_flf.FindMax(arr,lenght);
ecg_data.ecg_info.HeartRate.iMin =
dsp_flf.FindMin(arr,lenght);
//QRS_ms
for( i=0;i<lenght;i++)
{
//read qrs info and set it in arr
*(arr+i) = ecg_data.GetQRSms(i);
}
//calculate meandevmaxmin
ecg_data.ecg_info.QRS_ms.iMean =
dsp_flf.Mean(arr,lenght);
ecg_data.ecg_info.QRS_ms.iDev =
dsp_flf.StandardDeviation(arr,lenght);
ecg_data.ecg_info.QRS_ms.iMax =
dsp_flf.FindMax(arr,lenght);
ecg_data.ecg_info.QRS_ms.iMin =
dsp_flf.FindMin(arr,lenght);
//PR_ms
for( i=0;i<lenght;i++)
{
//read qrs info and set it in arr
*(arr+i) = ecg_data.GetPRms(i);
}
//calculate meandevmaxmin
ecg_data.ecg_info.PR_ms.iMean =
dsp_flf.Mean(arr,lenght);
ecg_data.ecg_info.PR_ms.iDev =
dsp_flf.StandardDeviation(arr,lenght);
ecg_data.ecg_info.PR_ms.iMax =
dsp_flf.FindMax(arr,lenght);
ecg_data.ecg_info.PR_ms.iMin =
dsp_flf.FindMin(arr,lenght);
//QT_QTc_ms
for( i=0;i<lenght;i++)
{
//read qrs info and set it in arr
*(arr+i) = ecg_data.GetQTQTcms(i);
}
//calculate meandevmaxmin]
ecg_data.ecg_info.QT_QTc_ms.iMean =
dsp_flf.Mean(arr,lenght);
ecg_data.ecg_info.QT_QTc_ms.iDev =
dsp_flf.StandardDeviation(arr,lenght);
ecg_data.ecg_info.QT_QTc_ms.iMax =
dsp_flf.FindMax(arr,lenght);
ecg_data.ecg_info.QT_QTc_ms.iMin =
dsp_flf.FindMin(arr,lenght);
//free memory from array
delete arr;
}
}
void CECG_1Dlg::FormatTestDlg()
{
CString str;
int age=0;
CString sage="";
//Finding the patients ages
COleDateTime this_year = COleDateTime::GetCurrentTime();
age = int(this_year.GetYear()) -
int(ecg_data.person.Birth_Date.GetYear());
sage.Format(" %dy.",age);
//Format the name control
str = "Name: "+ecg_data.person.sName_1+" "+ecg_data.person.sName_2+" "+
ecg_data.person.sName_3;
str = str + sage;
dlg_velo_test.m_sName = str;
//Format the name of the trainer
str = ecg_data.ecg_info.Confirm_By;
dlg_velo_test.m_sTrainerName = "Confirmed by: "+str;
////////////////////////////
//Format the measured values
////////////////////////////
//Format the heart rate
dlg_velo_test.m_sHeartRate.Format(
"Mean heart rate - %d�/min +-%d�/min (maximum:%d�/min minimum:%d�/min)",
ecg_data.ecg_info.HeartRate.iMean,
ecg_data.ecg_info.HeartRate.iDev,
ecg_data.ecg_info.HeartRate.iMax,
ecg_data.ecg_info.HeartRate.iMin);
//Format the QRSms
dlg_velo_test.m_sQRSms.Format(
"Mean QRS interval %dmsec. +-%dmsec. (maximum:%dmsec. minimum:%dmsec.)",
ecg_data.ecg_info.QRS_ms.iMean,
ecg_data.ecg_info.QRS_ms.iDev,
ecg_data.ecg_info.QRS_ms.iMax,
ecg_data.ecg_info.QRS_ms.iMin);
//Format the PRms
dlg_velo_test.m_sPRms.Format(
"Mean PR interval %dmsec +-%dmsec. (maximum:%dmsec. minimum:%dmsec.)",
ecg_data.ecg_info.PR_ms.iMean,
ecg_data.ecg_info.PR_ms.iDev,
ecg_data.ecg_info.PR_ms.iMax,
ecg_data.ecg_info.PR_ms.iMin);
//Format the QTQtcms
dlg_velo_test.m_sQTQTcms.Format(
"Mean QT_QTc interval %dmsec +-%dmsec. (maximum:%dmsec. minimum:%dmsec.)",
ecg_data.ecg_info.QT_QTc_ms.iMean,
ecg_data.ecg_info.QT_QTc_ms.iDev,
ecg_data.ecg_info.QT_QTc_ms.iMax,
ecg_data.ecg_info.QT_QTc_ms.iMin);
//Format info about blood preasure
dlg_velo_test.m_sbloodpreaure.Format("%d not used",
ecg_data.ecg_info.BloodPreasure.iMean);
//Format info about temperature
dlg_velo_test.m_stemperature.Format("%d not used",
ecg_data.ecg_info.Temperature.iMean);
//Check for recorded date, if is no recorded date set curent time
if(ecg_data.ecg_info.velo_test_date==0)
{
MessageBox("No ecg_test date! Now it will be set as system time!","No date",MB_OK);
ecg_data.ecg_info.velo_test_date = COleDateTime::GetCurrentTime();
}
dlg_velo_test.m_dTestDate = (ecg_data.ecg_info.velo_test_date);
/////////////////////////////
}
void CECG_1Dlg::OnBsavebmp2()
{
// TODO: Add your control notification handler code here
if(ecg_data.GetAllDataLenght()/2500>0)
{
CPerson* lpPerson;
lpPerson = &ecg_data.person;
CEcg_Info* lpEcg_Info;
lpEcg_Info = &ecg_data.ecg_info;
statistic_draw.PrintBMP(lpPerson,lpEcg_Info);
}
}
void CECG_1Dlg::ShowPulseDialog()
{
//dialog_pulse_meter was done
//in oninitdialog
//dlg_pulse_meter.Create(IDD_DPULSEMETER,this);
//So we can show it and continue working with program
if(b_dlgPulseMeter==0)
{
dlg_pulse_meter.ShowWindow(SW_SHOW);
dlg_pulse_meter.DrawPulse();
b_dlgPulseMeter = 1;
}
}
void CECG_1Dlg::HidePulseDialog()
{
//if pulse_dialog is opened close it
if(b_dlgPulseMeter==1)
{
dlg_pulse_meter.ShowWindow(SW_HIDE);
b_dlgPulseMeter = 0;
}
}
void CECG_1Dlg::ShowCurrPulse(int data_index)
{
if(b_dlgPulseMeter==1)
{
dlg_pulse_meter.s_CurrPulse.Format("%d",
i_QRS_count);
int syze = ecg_data.QRS_COUNT.GetSize();
if(syze > 0)
{
int pos=syze-1;
int count = 0;
int mean = 0;
do
{
mean = mean + ecg_data.QRS_COUNT.GetAt(pos);
pos--;
count++;
}
while((count<3)&(pos>0));
mean = mean/count;
dlg_pulse_meter.s_PastPulse.Format("%d",mean);
}
dlg_pulse_meter.DrawPulse();
}
}
void CECG_1Dlg::OnC50hz()
{
// TODO: Add your control notification handler code here
UpdateData(true);
UpdateData(false);
}
void CECG_1Dlg::OnC60hz()
{
// TODO: Add your control notification handler code here
UpdateData(true);
UpdateData(false);
}
void CECG_1Dlg::OnC40lol()
{
// TODO: Add your control notification handler code here
UpdateData(true);
UpdateData(false);
}
void CECG_1Dlg::OnCw50hz()
{
// TODO: Add your control notification handler code here
UpdateData(true);
UpdateData(false);
}
void CECG_1Dlg::OnCw40hz()
{
// TODO: Add your control notification handler code here
UpdateData(true);
UpdateData(false);
}
void CECG_1Dlg::OnCw067()
{
// TODO: Add your control notification handler code here
UpdateData(true);
UpdateData(false);
}
void CECG_1Dlg::OnBampl()
{
// TODO: Add your control notification handler code here
dsp_flf.Amplifier(AR_ECG,AR_ECG,2500,5);
OnButton1();
}
void CECG_1Dlg::OnBdspall()
{
// TODO: Add your control notification handler code here
int count = ecg_data.GetAllDataLenght()/2500;
if(count>0)
{
//Format the buttons
dlg_dsp_all.m_bQRS = 0;
dlg_dsp_all.m_bNoht50Hz = 0;
dlg_dsp_all.m_bLow100Hz = 0;
dlg_dsp_all.m_bLow40Hz = 0;
dlg_dsp_all.m_bHigh068Hz = 0;
int result = dlg_dsp_all.DoModal();
if(result == IDOK)
{
CString str;
//because we will recalculate all data
//we can remove it
m_ctldata.ResetContent();
// dsp_flf.LoadFilterKernels(250);
for(int i=0;i<count;i++)
{
//reads data from i*2500 to i*2500+2500
GetDataFrom(AR_ECG,i,2500);
//normalize array because it need or may be not normalized
//
if(dlg_dsp_all.m_bQRS == 1)
dsp_ecg.SetECG(AR_ECG,2500,AR_REV,&i_QRS_count,&i_QRS_ms,
&i_PR_ms,&i_QT_QTc_ms,m_select_segment);
if(dlg_dsp_all.m_bNoht50Hz == 1)
dsp_flf.WFilter_Noht(AR_ECG,AR_ECG,2500,250,50);
if(dlg_dsp_all.m_bLow40Hz == 1)
dsp_flf.WFilter_Low40Hz(AR_ECG,AR_ECG,2500,250,0.67);
if(dlg_dsp_all.m_bLow100Hz == 1)
dsp_flf.WFilter_Low100Hz(AR_ECG,AR_ECG,2500,250,100);
if(dlg_dsp_all.m_bHigh068Hz == 1)
dsp_flf.WFilter_High(AR_ECG,AR_ECG,5000,1,250,0.67);
//dsp_flf.SetArrToNormalize(AR_ECG,2500);
// ecg_data.GetInfoFrom(i,&i_QRS_count,&i_QRS_ms,&i_PR_ms,
// &i_QT_QTc_ms,&hh,&mm);
// dsp_flf.Delta2(AR_ECG,AR_ECG,2500);
SetDataAt(AR_ECG,i,2500);
//Format a string to be fitt in m_ctldata control
str.Format("%d:%d %d�/���",hh,mm,i_QRS_count);
//inserts a string at current position
m_ctldata.InsertString(i,str);
}
}
}
OnBtest();
}
void CECG_1Dlg::OnRadio1()
{
// TODO: Add your control notification handler code here
UpdateData(true);
dsp_ecg.SetECG(AR_ECG,2500,AR_REV,&i_QRS_count,&i_QRS_ms,
&i_PR_ms,&i_QT_QTc_ms,m_select_segment);
OnButton1();
UpdateData(false);
}
void CECG_1Dlg::OnLButtonDblClk(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
if(i_bmp==1)
{
//Calculate minute array positions
byte old_min,min=0;
byte old_hour,hour=0;
//Heare we will store the begining positions of
//each minute, bacause in one minute we may have
//6 - 10secconds reccords
CWordArray ctl_pos;
ctl_pos.RemoveAll();
int old_i=0;
// dsp_flf.Message(m_ctldata.GetCount()-1);
for(int i=0;i<m_ctldata.GetCount()-1;i++)
{
ecg_data.GetPosTime(i,&old_hour,&old_min);
old_i = i;
//Loop untill old minute is gone
do
{
i++;
ecg_data.GetPosTime(i,&hour,&min);
}
//Important to be old_min == min
while(old_min == min);
//old_i wiw show thw bwgining of each minute
ctl_pos.Add(old_i);
}
// dsp_flf.Message(ctl_pos.GetSize());
////////////////////////////////////////
int x = point.x;
int y = point.y;
//if mouse is on m_ctldata rect
if(x>220&x<720&y>120&y<330)
{
//after this select the pointered date
//Calculate the selected minute
int cur_min = (x-220)/2;
int c_index=0;
//If calculated minute is < minute array
//show pointer of a list box on te position
//that shows the value from ctl_pos(index)
if(cur_min <= ctl_pos.GetSize())
{
c_index = ctl_pos.GetAt(cur_min);
m_ctldata.SetCurSel(c_index);
}
}
}
CDialog::OnLButtonDblClk(nFlags, point);
}
void CECG_1Dlg::OnBecgprint()
{
// TODO: Add your control notification handler code here
if(ecg_data.GetAllDataLenght()/2500>0)
{
CPrintDialog dlgPrint(FALSE,PD_ALLPAGES,NULL);
if(dlgPrint.DoModal()==IDOK)
{
CDC dcPrint;
dcPrint.Attach(dlgPrint.GetPrinterDC());
DOCINFO PrintJob;
PrintJob.cbSize = sizeof(PrintJob);
PrintJob.lpszDocName = "BMP printing";
PrintJob.lpszOutput = NULL;
PrintJob.lpszDatatype = NULL;
PrintJob.fwType = NULL;
dcPrint.SetMapMode(MM_LOMETRIC);
if(dcPrint.StartDoc(&PrintJob)>=0)
{
dcPrint.StartPage();
//Draw ECG single record information
CFont Font;
Font.CreateFont(40,20,-900,0,FW_DONTCARE,FALSE,FALSE,0,
DEFAULT_CHARSET,OUT_CHARACTER_PRECIS,
CLIP_CHARACTER_PRECIS,DEFAULT_QUALITY,
DEFAULT_PITCH|FF_DONTCARE,
"MS Sans Serif");
CFont* pOldFont = dcPrint.SelectObject(&Font);
dcPrint.TextOut(770,-40,"EGN: " + ecg_data.person.sEGN);
dcPrint.TextOut(730,-40,"Name: "+
ecg_data.person.sName_1 + " "+
ecg_data.person.sName_2 + " "+
ecg_data.person.sName_3);
CString date;
date = ecg_data.ecg_info.velo_test_date.Format("%Yy.%mm.%dd/");
dcPrint.TextOut(690,-40,"ECG record info: "+
date +
s_ECG_Info);
for(int i=0;i<2500;i++)
{
dcPrint.MoveTo(450+AR_ECG[i]/3,-20-i);
dcPrint.LineTo(450+AR_ECG[i+1]/3,-20-i-1);
}
for(i=0;i<5;i++)
{
if(i!=2)
{
dcPrint.MoveTo(250+100*i,-20);
dcPrint.LineTo(250+100*i,-2500);
}
}
CString str;
for(i=0;i<11;i++)
{
str.Format("|%ds",i);
dcPrint.TextOut(290,-20-i*250,str);
}
dcPrint.EndPage();
dcPrint.EndDoc();
//return the old font
dcPrint.SelectObject(pOldFont);
}
dcPrint.DeleteDC();
}
}
}