MFC C/C++ Source Code Example of Using DirectDSP®
Source Code Home
Below is a MFC C/C++ source code example of using off-the-shelf DSP/analog
hardware to perform data acquisition (or playback). Please note copyright
notices below.
////////////////////////////////////////////////////////////////////////////
// by Norma Antonanzas-Barroso
// c 1996 The Regents of the University of California
// All rights reserved. You may redistribute this program without restriction,
// provided 1) this copyright notice appears on all copies; and 2) no fee
// is charged. Note that technical support is not avilable for this code.
////////////////////////////////////////////////////////////////////////////
// This is a program to test DirectDSP in Windows
// It opens a dialog box with a button control to PLAY and an edit
// control to enter the file number to play.
// doitview.cpp : implementation file
//
// DSPower-HwLib / DirectDSP™ software package include files
#include "enmgr.h" // Engine Manager
#include "hwmgr.h" // Hardware Manager
#include "hwlib.h" // Hardware Library
#include "stdafx.h"
#include "doit.h"
#include "doitview.h"
#include "fcntl.h"
#include "sys\types.h"
#include "sys\stat.h"
#include "io.h"
/////////////////////////////////////////////////////////////////////////////
// CDoitView
IMPLEMENT_DYNCREATE(CDoitView, CFormView)
CDoitView::CDoitView()
: CFormView(CDoitView::IDD)
{
//{{AFX_DATA_INIT(CDoitView)
m_FNumber = "1";
//}}AFX_DATA_INIT
m_hBuf = NULL;
m_hBoard = NULL;
m_fBoardInitialized = FALSE;
m_pBuf = NULL;
}
CDoitView::~CDoitView()
{
if ( m_fBoardInitialized )
DSDisableBoard ( m_hBoard );
if ( m_hBoard != NULL )
{
DSCancelWaitBuffer ( m_hBoard, 0 );
DSResetProcessor ( m_hBoard, 0x01 );
DSFreeBoard ( m_hBoard );
}
if ( hEngine != NULL )
{
DSUnregisterEngineMsgWnd ( hEngine, DS_REMW_SETDSPDATARDYMSG );
DSEngineClose ( hEngine );
}
if ( m_hBuf != NULL )
GlobalFree ( m_hBuf );
close ( m_file );
}
void CDoitView::DoDataExchange(CDataExchange* pDX)
{
CFormView::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CDoitView)
DDX_Text(pDX, IDC_EDIT_FILENUMBER, m_FNumber);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CDoitView, CFormView)
ON_MESSAGE(WM_DSPENGINE_BUFRDY, OnDspEngineBufferReady)
//{{AFX_MSG_MAP(CDoitView)
ON_BN_CLICKED(IDC_BUTTON_PLAY, OnButtonPlay)
ON_WM_CREATE()
ON_EN_CHANGE(IDC_EDIT_FILENUMBER, OnChangeEditFilenumber)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CDoitView message handlers
void CDoitView::OnButtonPlay()
{
unsigned int np;
char tmpstr[100];
short int ChanList[MAXCHAN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
DWORD dwFsMode;
float FsActual;
int i;
short int NumChan = 1;
HWND hwndDoit = NULL;
short * temp = NULL;
WORD wBoardClass;
unsigned int ni;
unsigned int nb;
// INITIALIZATION. This has to be repeated every time it plays, it cannot go
// just in CREATE.
// interrogate engine for board type values
wBoardClass = DSGetBoardClass(m_hBoard);
// send down some important variables:
DSPutDSPProperty(m_hBoard, DSP_BOARDCLASS, wBoardClass & 0x0ff); // main
type in low byte
DSPutDSPProperty(m_hBoard, DSP_BOARDSUBCLASS, wBoardClass >> 8); // subtype
in high byte
DSPutDSPProperty(m_hBoard, DSP_OPMODE, 1); // play back is mode 1
// acquisition is mode 0
DSPutDSPProperty(m_hBoard, DSP_SCALEOUT, 256L);
DSPutDSPProperty(m_hBoard, DSP_FILTTYPE1, 0); // disable trace 1
real-time filter
DSPutDSPProperty(m_hBoard, DSP_FILTTYPE2, 0); // disable trace 2
real-time filter
DSPutDSPProperty(m_hBoard, DSP_TRIGLEVEL, 0); // free-run triggering
DSPutDSPProperty(m_hBoard, DSP_TRIGCHANLIST, 0);
DSPutDSPProperty(m_hBoard, DSP_BUFLEN, BUFFSIZE); // buffer size,
the real one
DSPutDSPProperty(m_hBoard, DSP_HOSTBUFNUM, 0); // starting buffer numbers
DSPutDSPProperty(m_hBoard, DSP_BUFNUM, 0);
DSPutDSPProperty(m_hBoard, DSP_NUMCHAN, NumChan ); // number of channels
DWORD dw = 0;
ChanList[0] = 0;
DSPutDSPProperty(m_hBoard, DSP_CHANLIST, dw); // channel list
DSPutDSPProperty(m_hBoard, DSP_GAINLIST, 0); // gain list
// determine sampling rate ctrl. reg. value, and actual rate (closest rate
possible to desired);
// CalcSampFreq returns ctrl. reg. value directly, uses ptr to return actual
sampling frequency (in Hz)
FsActual = 20000.;
dwFsMode = DSCalcSampFreq(m_hBoard, FsActual, NumChan, (short far*)&ChanList,
&FsActual);
DSPutDSPProperty(m_hBoard, DSP_FSMODE, dwFsMode); // sampling rate
control register (mode value)
DSPutDSPProperty(m_hBoard, DSP_FSVALUE, *((long*)&FsActual)); // actual
sampling rate (in Hz)
// END INITIALIZATION
// Get the pointer to the allocated memory, read data into host buffer
// in two instances because it only takes unsigend int and we are reading
// 80000 bytes.
if ( m_FileNumber >200 )
{
MessageBox ( "too large file number", "1 Doit Test Prog: read failed",
MB_OK);
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
return;
}
temp = new short[BUFFSIZE/2];
if ( temp == NULL )
{
MessageBox ( "new failed", "Doit Test Prog", MB_OK);
delete[] temp;
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
return;
}
m_pBuf = (short huge*) GlobalLock ( m_hBuf );
if ( m_pBuf == NULL )
{
MessageBox ( "GlobalLock failed", "Doit Test Prog",
MB_OK);
delete[] temp;
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
return;
}
lseek ( m_file, 1024L + ( m_FileNumber - 1 ) * sizeof ( short ) *
50000L, SEEK_SET );
ni = (unsigned int) BUFFSIZE / 2;
nb = ni * (unsigned int)sizeof(short);
np = (unsigned int )_read ( m_file, temp, nb );
if ( np != nb )
{
GlobalUnlock ( m_hBuf );
MessageBox ( "data < BUFFSIZE", "1 Doit Test Prog: read failed",
MB_OK);
delete[] temp;
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
return;
}
for ( i = 0; i < BUFFSIZE/2; i++ )
m_pBuf[i] = temp[i];
np = (unsigned int )_read ( m_file, temp, nb );
if ( np != nb )
{
GlobalUnlock ( m_hBuf );
MessageBox ( "data < BUFFSIZE", "2 Doit Test Prog: read failed",
MB_OK);
delete[] temp;
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
return;
}
for ( i = 0; i < BUFFSIZE/2; i++ )
m_pBuf[i+BUFFSIZE/2] = temp[i];
delete[] temp;
// move the data to the board memory, send BUFFSIZE 0's at the end to
// give time for the data ready message to be issued
if ( ( DSPutMem ( m_hBoard, DS_GM_LINEAR_DATA, m_dwBufferBaseAddr,
DS_GM_SIZE16, m_pBuf,(DWORD) ( BUFFSIZE*2 ) ) ) == NULL )
{
itoa ( DSGetEngineErrorStatus ( hEngine ), tmpstr, 10 );
MessageBox ( tmpstr, "Doit Test Prog: DSLoadFileProcessor failed",
MB_OK);
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
return;
}
// start to play
DSRunProcessor ( m_hBoard, 0x01 );
// initialize wait for buffer: send a WM_DSPENGINE_BUFRDY message when it
// finished playing one buffer
DSWaitForBuffer( m_hBoard, 0, NULL, DS_WFB_POLLED);
// free the pointer
GlobalUnlock ( m_hBuf );
return;
}
/////////////////////////////////////////////////////////////////////////
void CDoitView::OnChangeEditFilenumber()
{
UpdateData (TRUE);
m_FileNumber = (UINT) atoi ( m_FNumber );
}
/////////////////////////////////////////////////////////////////////////
// Board sends this message when finished reading BUFFSIZE points, the
// remaining zeros in the buffer guaranty silence between the issue of
// the message and the response by this function
LRESULT CDoitView::OnDspEngineBufferReady ( WPARAM, LPARAM )
{
// reset DSPboard, processor 0 only
DSResetProcessor ( m_hBoard, 0x01 );
return 0L;
}
/////////////////////////////////////////////////////////////////////////
void CDoitView::OnInitialUpdate ( void )
{
// SIGNALOGIC requirements here:
DWORD dwMemSize;
HWND hwndDoit = NULL;
char tmpstr[100];
short int ChanList[MAXCHAN] = { 0, 0, 0, 0, 0, 0, 0, 0 };
short int NumChan = 1;
m_hBuf = NULL;
m_hBoard = NULL;
m_fBoardInitialized = FALSE;
m_pBuf = NULL;
strcpy ( m_szBoard, "SIG32C-L" ); // board designator
hwndDoit = GetSafeHwnd (); // get window handler
if ( hwndDoit == NULL )
{
MessageBox ( "NULL window handle", "Doit Test Prog",
MB_OK);
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
}
DSShowEngMgrStatusWindow(); // debugging: show status window
hEngine = DSEngineOpen(DS_EO_HSA, NULL); // open HyperSignal-Acoustics
if ( !hEngine )
{
itoa ( DSGetHWLibErrorStatus(), tmpstr, 10 );
MessageBox ( tmpstr, "Doit Test Prog: DSEngineOpen failed", MB_OK);
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
}
// assign a board handle: engine handle, board designator string,
instruction set, IO base addr, Mem base addr
m_hBoard = DSAssignBoard ( hEngine, m_szBoard,
NULL, NULL, NULL ); // use defaults
if ( m_hBoard == NULL )
{
itoa ( DSGetHWLibErrorStatus(), tmpstr, 10 );
MessageBox ( tmpstr, "Doit Test Prog: DSAssignBoard", MB_OK);
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
}
// initialize the board; make sure it's installed and responded
m_fBoardInitialized = DSInitBoard(m_hBoard);
if ( !m_fBoardInitialized )
{
itoa ( DSGetEngineErrorStatus ( hEngine ), tmpstr, 10 );
MessageBox ( tmpstr, "Doit Test Prog: DSInitBoard failed",
MB_OK);
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
}
// load executable DSP code file
if (!DSLoadFileProcessor ( m_hBoard, NULL, 1 ) )
{
itoa ( DSGetEngineErrorStatus ( hEngine ), tmpstr, 10 );
MessageBox ( tmpstr, "Doit Test Prog: DSLoadFileProcessor failed",
MB_OK);
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
}
// get the memory size in 16 bits words
dwMemSize = DSGetMemSize ( m_hBoard, 0x01 );
if ( dwMemSize < 2*BUFFSIZE )
{
MessageBox ( "buffer size < BUFFSIZE", "Doit Test Prog",
MB_OK);
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
}
// get address of output time domain data
m_dwBufferBaseAddr = DSGetDSPProperty ( m_hBoard, DSP_TIMDATAADDR );
// reset DSPboard, processor 0 only
DSResetProcessor ( m_hBoard, 0x01 );
// register callback window for buffer ready messages
UINT ret = DSRegisterEngineMsgWnd ( hEngine, DS_REMW_SETDSPDATARDYMSG,
hwndDoit );
if ( !ret )
{
itoa ( DSGetEngineErrorStatus ( hEngine ), tmpstr, 10 );
MessageBox ( tmpstr, "Doit Test Prog: DSRegisterEngine failed",
MB_OK);
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
}
// allocate some memory to hold board buffers
DWORD nbytes = 2 * (DWORD )BUFFSIZE * ( DWORD )sizeof ( short );
m_hBuf = GlobalAlloc ( GMEM_ZEROINIT | GMEM_MOVEABLE, nbytes );
if ( m_hBuf == NULL )
{
MessageBox ( "GlobalAlloc failed", "Doit Test Prog",
MB_OK);
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
}
// open the file
char myfile[] = "doit.voi";
m_file = _open ( myfile, _O_BINARY | _O_RDONLY );
if ( m_file == -1 )
{
MessageBox ( "Cannot open ", "Doit Test Prog",
MB_OK);
AfxGetMainWnd()->PostMessage ( WM_CLOSE );
}
UpdateData ( FALSE );
m_FileNumber = (UINT) atoi ( m_FNumber );
}