Follow us Follow us Signalogic on LinkedIn

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 ); 
}