Buffer Interface
CircClassExample.cpp

This is an example of how to use the CircularInterface class.

/***************************************************************************
*
* CirClassExample.cpp
*
* This application uses the CircularInterface class to acquire images
* into a circular buffer. This application is equivalent to the Circular.c
* application, the difference being the Circular.c application
* uses the Bi API and this application uses the CircularInterface class.
*
* There are several advantages to using the CircularInterface class
* that are demonstrated in this application.
* The advantages being:
* 1. Fewer method/function calls to accomplish sequence capture.
* 2. No need to call cleanup methods/functions.
* 3. Fewer method/function parameters.
* 4. Improved error handling by throwing exceptions.
*
* We encouraged you to compare this application to the Circular.c
* application to see the advantages for yourself.
*
* This example demonstrates the use of CircularInterface class.
*
* Copyright (C) 2004 by BitFlow, Inc. All Rights Reserved.
*
***************************************************************************/
#include "stdafx.h"
#include "CircClassExample.h"
#include <conio.h>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// Threads
UINT WaitForBufferDone(LPVOID lpdwParam);
UINT CirErrorThread(LPVOID lpdwParam);
MSG Msg;
BFBOOL endTest = FALSE;
int hDspSrf = -1; // handle to display surface
CWinApp theApp;
using namespace std;
using namespace BufferAcquisition;
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(BFNULL), BFNULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
BFU32 boardType, boardNum, init, serNum;
char ch;
BFU32 numBuffers = 50;
BFU32 cirSetupOptions = 0;
BFU32 errorMode = CirErStop;
CWinThread* pErrorThread;
CWinThread* pFrameDoneThread;
if( DoBrdOpenDialog(BOD_BRD_NUM_NON_FAMILY|BOD_HIDEJUSTOPEN, FF_BITFLOW_MODERN, &boardType, &boardNum,
&init, &serNum) )
{
return -1;
}
try
{
cout << "Creating instance of circular interface." << endl;
CircularInterface board(boardNum, numBuffers, errorMode,
cirSetupOptions);
// Create display surface to view sequence.
if(!DispSurfCreate((PBFS32)&hDspSrf, board.getBrdInfo(BiCamInqXSize),
board.getBrdInfo(BiCamInqYSize0),
board.getBrdInfo(BiCamInqBitsPerPixDisplay), BFNULL))
{
cout << "Couldn't create display surface" << endl;
return 1;
}
pErrorThread = AfxBeginThread(CirErrorThread, &board, THREAD_PRIORITY_HIGHEST);
if(pErrorThread == BFNULL)
return 1;
pFrameDoneThread = AfxBeginThread(WaitForBufferDone, &board, THREAD_PRIORITY_HIGHEST);
if(pFrameDoneThread == BFNULL)
return 1;
printf("\nPress G (as in Go) to start Acquisition ");
printf(" Press S to Stop Acquisition \n");
printf("Press P to Pause Press C to Continue\n");
printf("Press A to Abort\n");
printf("Press X to exit test\n\n");
while(!endTest)
{
// Wait here for a keyboard stroke
while(!BFkbhit() && !endTest)
{
if(PeekMessage(&Msg,BFNULL,0,0,PM_REMOVE))
DispatchMessage(&Msg);
else
Sleep(10);
}
if(!endTest)
ch = BFgetch();
else
ch = 'X';
cout << endl;
switch(toupper(ch))
{
case 'G': // Start acquisition
board.cirControl(BISTART, BiAsync);
cout <<"Circular Acquisition Started." << endl;
break;
case 'P':// Pause acquisition
board.cirControl(BIPAUSE, BiAsync);
cout <<"Circular Acquisition Paused." << endl;
break;
case 'C':// Resume acquisition
board.cirControl(BIRESUME, BiAsync);
cout <<"Circular Acquisition Resumed." << endl;
break;
case 'S':// Stop acquisition
board.cirControl(BISTOP, BiAsync);
break;
case 'A':// Abort acquisition
board.cirControl(BIABORT, BiAsync);
break;
case 'X':// Exit application
if(board.getStartAcqFlag())
board.cirControl(BIABORT, BiAsync);
endTest = TRUE;
break;
default:
cout <<"Key not Recognized, Try Again" << endl;
break;
}
}
CString Str;
Str.Format("\nCaptured %d Frames\nMissed %d Frames\n",
board.getNumFramesCaptured(), board.getNumFramesMissed() );
cout << Str << endl;
BFRC error = board.getCirError();
while(error != BI_OK)
{
board.showError(error);
error = board.getCirError();
}
cout <<"\nPress Any Key to Continue." << endl;
while(!BFkbhit())
{
/* needed for display window */
if(PeekMessage(&Msg,BFNULL,0,0,PM_REMOVE))
DispatchMessage(&Msg);
else
Sleep(0);
}
// absorb key stroke
if (BFkbhit()) BFgetch();
// Close Display window
DispSurfClose(hDspSrf);
// No need to clean up resources, the destructor of the
// CircularInterface class will handle clean up.
}
catch(BFException e)
{
nRetCode = 1;
}
if(DispSurfIsOpen(hDspSrf))
{
// Close Display window
DispSurfClose(hDspSrf);
}
// Wait for threads to end
DWORD exitCode;
while(GetExitCodeThread(pErrorThread->m_hThread,&exitCode) &&
exitCode == STILL_ACTIVE)
{
Sleep(10);
}
while(GetExitCodeThread(pFrameDoneThread->m_hThread,&exitCode) &&
exitCode == STILL_ACTIVE)
{
Sleep(10);
}
}
return nRetCode;
}
UINT WaitForBufferDone(LPVOID lpdwParam)
{
CircularInterface* board = (CircularInterface*) lpdwParam;
BFU32 rv;
BiCirHandle cirHandle;
BFTickRec T0, T1;
try
{
// loop until cleanup is called
rv = board->waitDoneFrame(INFINITE, &cirHandle);
BFTick(&T0);
{
// print buffer info if a valid buffer has been acquired
if(rv == BI_CIR_STOPPED)
cout <<"Circular Acquisition Stopped." << endl;
else if(rv == BI_CIR_ABORTED)
cout <<"Circular Acquisition Aborted." << endl;
cout <<"BiSeqWaitDone has timed out." << endl;
else if(rv == BI_ERROR_CIR_WAIT_FAILED)
cout <<"The wait in BiSeqWaitDone Failed." << endl;
else if(rv == BI_ERROR_QEMPTY)
cout <<"The queue was empty." << endl;
else
{
// only update display every 30 msec
if (BFTickDelta(&T0, BFTick(&T1)) > 30)
{
// This new function will format the image data for display,
// then display the image. This reduces a lot of code. (See
// Circular.c)
if(!DispSurfFormatBlit(hDspSrf, cirHandle.pBufData,
board->getBrdInfo(BiCamInqBitsPerPix), BFDISP_FORMAT_NORMAL))
{
cout << "Could not update the display surface" << endl;
return 1;
}
BFTick(&T0);
}
// Mark the buffer as AVAILABLE after processing
board->setBufferStatus(cirHandle, BIAVAILABLE);
// output some stats
cout << setfill('0');
cout << "Buffer: "<< setw(8) << cirHandle.BufferNumber << " ";
cout << "Count: "<< setw(8) << cirHandle.FrameCount << " ";
cout << "SrcTag: "<< setw(8) << cirHandle.CXPSrcTag << " ";
cout << "XOffs: "<< setw(8) << cirHandle.CXPXOffset << " ";
cout << "YOffs: "<< setw(8) << cirHandle.CXPYOffset << " ";
cout << '\r';
}
rv = board->waitDoneFrame(INFINITE, &cirHandle);
}
}
catch(BFException e)
{
// End application if an error occurs
endTest = TRUE;
return 1;
}
return 0;
}
UINT CirErrorThread(LPVOID lpdwParam)
{
CircularInterface* board = (CircularInterface*) lpdwParam;
while(board->cirErrorWait() != BI_CIR_CLEANUP)
{
cout << "ErrorThread - Acquisition Error!!" << endl;
}
return 0;
}