/*****************************************************************************
CIsimpleDGMA.c Source for BitFlow CI lib DirectGMA example program
Sep 28, 2015 CIW/SJT
© Copyright 2015, BitFlow, Inc. All rights reserved.
Tabstops are 4
$Author: steve $
$Date: 2020/10/02 23:30:13 $
$Id: CIsimpleDGMA.c,v 1.7 2020/10/02 23:30:13 steve Exp $
*****************************************************************************/
/*==========================================================================*/
/*
** For access to command line display.
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
/*
** For checking for keypress
*/
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
/*
** For access to BitFlow camera interface library.
*/
#include "BFciLib.h"
#include "BFPCI2PCI.h"
/*--------------------------------------------------------------------------*/
/*
** Bring in the necessary AMD headers
*/
#include "CL/opencl.h"
#include "cl_ext.h"
/*==========================================================================*/
static int sExitAns = 0; /* program exit code */
static tCIp sCIp = NULL; /* BitFlow device open token */
static int sNdx = 0; /* BitFlow device index */
static int sNframes = 4; /* number of DMA frame buffers */
static int sNdx2 = 0; /* AMD device index */
static int sMaxFrames = 0; /* total frames to display */
static int sSkipFrames = 0; /* skip between display */
static int sDidFrames = 0; /* total frames handled */
static int sBGok = 0; /* ok to be in background */
static int sPageSize = 0; /* system dependent */
/*--------------------------------------------------------------------------*/
#define SHOW(x) { (void)printf x ; (void)fflush(stdout); }
#define ERR(x) { SHOW(("ERR: ")); SHOW(x); }
#ifdef DO_DEBUG_DGMA
#define DB(x) { SHOW(("DB: ")); SHOW(x); }
#else
#define DB(x)
#endif
static char *sArgv0 = NULL; /* name of executable */
static void ShowHelp(void)
{
SHOW(("%s of " __DATE__ " at " __TIME__ "\n", sArgv0));
SHOW((" -h display this message and exit\n"));
SHOW(("\n"));
SHOW((" -x ndx choose available BitFow device ndx (default 0)\n"));
SHOW((" -n nFrames change number of DMA frame buffers (default 4)\n"));
SHOW((" -y ndx choose available AMD device ndx (default 0)\n"));
SHOW((" -m maxFrames max frames to display (default infinite)\n"));
SHOW((" -s skipFr frames to skip between display (default 0)\n"));
SHOW((" -b program is backgrounded (no newline exit)\n"));
SHOW(("\n"));
SHOW((" CIsimpleDGMA: init a VFG and display pixels from GPU memory\n"));
SHOW((" display ends with newline\n"));
SHOW(("\n"));
}
/*==========================================================================*/
#include <time.h>
#include <sys/timeb.h>
static tCIDOUBLE GetTime(void)
/*
** Return fractional seconds
*/
{
tCIDOUBLE ans = 0.0;
#ifdef _POSIX_TIMERS
struct timespec tp;
(void)clock_gettime(CLOCK_MONOTONIC_RAW, &tp);
ans = (tCIDOUBLE) tp.tv_sec;
ans += ((tCIDOUBLE) tp.tv_nsec) / 1000000000.0;
#else
struct timeb tb;
(void)ftime(&tb);
ans = tb.millitm;
ans /= 1000.0;
ans += tb.time;
#endif
return (ans);
}
/*--------------------------------------------------------------------------*/
static int DecodeArgs(int argc, char **argv)
/*
** Parse the input arguments.
*/
{
char *str;
argv += 1;
argc -= 1; /* skip program name */
while (argc-- > 0)
{
str = *argv++;
if (str[0] != '-')
{
ERR(("Do not know '%s' arg\n", str));
ShowHelp();
return (1);
}
switch (str[1])
{
case 'h':
ShowHelp();
exit(0);
case 'x':
(void)sscanf(*argv, "%d", &sNdx);
argv += 1;
argc -= 1;
break;
case 'n':
(void)sscanf(*argv, "%d", &sNframes);
argv += 1;
argc -= 1;
break;
case 'y':
(void)sscanf(*argv, "%d", &sNdx2);
argv += 1;
argc -= 1;
break;
case 'b':
sBGok = 1;
break;
case 'm':
(void)sscanf(*argv, "%d", &sMaxFrames);
argv += 1;
argc -= 1;
break;
case 's':
(void)sscanf(*argv, "%d", &sSkipFrames);
argv += 1;
argc -= 1;
break;
default:
ERR(("Do not know arg '%s'\n", str));
ShowHelp();
sExitAns = 1;
return (sExitAns);
}
}
return (kCIEnoErr);
}
/*--------------------------------------------------------------------------*/
static int CheckForKeyboardInput(void)
/*
** Return 0 if no input available from stdin, 1 else
**
** Note: the console needs a newline in order to post input.
*/
{
fd_set exceptfds, readfds, writefds;
struct timeval tv;
int ans;
char buff[1024];
FD_ZERO(&exceptfds);
FD_ZERO(&readfds);
FD_ZERO(&writefds);
FD_SET(fileno(stdin), &readfds);
(void)memset(&tv, '\0', sizeof(struct timeval));
ans = select(1, &readfds, &writefds, &exceptfds, &tv);
if ((ans == 1) && FD_ISSET(fileno(stdin), &readfds))
{
/*
** Consume the line.
*/
(void)fgets(buff, 1024, stdin);
return (1);
}
return (0);
}
/*--------------------------------------------------------------------------*/
static cl_context sContext = NULL;
static cl_command_queue sCommandQueue = NULL;
static clEnqueueMakeBuffersResidentAMD_fn sMakeBuffersResidentAMD = NULL;
static cl_mem *sBufs = NULL;
static cl_mem sOut = NULL;
static tCIU8 *sOutRAM = NULL;
static cl_bus_address_amd *sDMAaddrs = NULL;
/*--------------------------------------------------------------------------*/
static void TermDGMA(void)
{
int i;
cl_event event;
cl_int clrc;
if (NULL != sDMAaddrs)
{
free(sDMAaddrs);
}
sDMAaddrs = NULL;
if (NULL != sBufs)
{
for (i = 0; i < sNframes; i++)
{
if (NULL != sBufs[i])
{
(void)clReleaseMemObject(sBufs[i]);
}
}
free(sBufs);
}
sBufs = NULL;
if (NULL != sOut)
{
(void)clReleaseMemObject(sOut);
}
sOut = NULL;
if (NULL != sCommandQueue)
{
(void)clFinish(sCommandQueue);
(void)clReleaseCommandQueue(sCommandQueue);
}
sCommandQueue = NULL;
if (NULL != sContext)
{
(void)clReleaseContext(sContext);
}
sContext = NULL;
return;
}
/*--------------------------------------------------------------------------*/
/*
** The interface clCreateCommandQueue() is now deprecated and the docs say to
** use clCreateCommandQueueWithProperties() instead.
**
** However some installs/upgrades end up with stale libOpenCL.* so here
** is a token to force use of the deprecated call. The compiler warns but
** the linker is happy.
**
#define BF_FORCE_OLD_WQ 1
**
*/
#ifdef CL_VERSION_2_0
#define USE_OLD_WQ 0
#else
#define USE_OLD_WQ 1
#endif
#ifdef BF_FORCE_OLD_WQ
#ifdef USE_OLD_WQ
#undef USE_OLD_WQ
#endif
#define USE_OLD_WQ 1
#endif
/*--------------------------------------------------------------------------*/
static int InitDGMA(tCIU64 frameSize) /* initialize the GPU hardware */
{
cl_int clrc;
cl_uint oclPlatformCnt = 0, ndx, ndx2;
cl_platform_id *oclPlatforms = NULL;
#define MAX_PROP_SZ 4096
char buff[MAX_PROP_SZ];
cl_device_id did[MAX_PROP_SZ / sizeof(cl_device_id)];
int count = -1, i;
int rc = 1;
size_t sz;
tCIU64 roundSize = frameSize + (sPageSize - 1), x;
#if USE_OLD_WQ == 0
cl_queue_properties properties;
#endif
/*
** Find available hardware
*/
clrc = clGetPlatformIDs(0, NULL, &oclPlatformCnt);
if (CL_SUCCESS != clrc)
{
ERR(("InitDGMA: clGetPlatformIDs() failed (%d)\n", clrc));
return (1);
}
if (0 >= oclPlatformCnt)
{
ERR(("InitDGMA: no OpenCL platforms available on this system\n"));
return (1);
}
oclPlatforms = malloc(oclPlatformCnt * sizeof(cl_platform_id));
if (NULL == oclPlatforms)
{
ERR(("InitDGMA: cannot get memory %d platformIDs\n", oclPlatformCnt));
return (1);
}
clrc = clGetPlatformIDs(oclPlatformCnt, oclPlatforms, NULL);
if (CL_SUCCESS != clrc)
{
ERR(("InitDGMA: clGetPlatformIDs failed (%d)\n", clrc));
goto andOut;
}
for (ndx = 0; ndx < oclPlatformCnt; ndx++)
{
clrc = clGetPlatformInfo(oclPlatforms[ndx], CL_PLATFORM_VENDOR, MAX_PROP_SZ, buff, NULL);
if (CL_SUCCESS != clrc)
{
ERR(("InitDGMA: clGetPlatformInfo %d failed (%d)\n", ndx, clrc));
goto andOut;
}
#define AMD_STR "Advanced Micro Devices, Inc."
if (0 == strcmp(AMD_STR, buff))
{
goto gotAMDplatform;
}
}
ERR(("InitDGMA: found no AMD devices\n"));
goto andOut;
gotAMDplatform:
/*
** Now load the required extension
*/
sMakeBuffersResidentAMD = (clEnqueueMakeBuffersResidentAMD_fn)clGetExtensionFunctionAddressForPlatform(oclPlatforms[ndx],"clEnqueueMakeBuffersResidentAMD");
if (NULL == sMakeBuffersResidentAMD)
{
ERR(("InitDGMA: cannot get AMD func\n"));
goto andOut;
}
/*
** Create a context
*/
{
cl_context_properties oclContextProps[] = {
CL_CONTEXT_PLATFORM,
(cl_context_properties) oclPlatforms[ndx],
0
};
sContext = clCreateContextFromType(oclContextProps, CL_DEVICE_TYPE_GPU, NULL, NULL, &clrc);
if ((NULL == sContext) || (CL_SUCCESS != clrc))
{
ERR(("InitDGMA: clCreateContextFromType failed (%d)\n", clrc));
goto andOut;
}
}
clrc = clGetContextInfo(sContext, CL_CONTEXT_DEVICES, MAX_PROP_SZ, did, &sz);
if (CL_SUCCESS != clrc)
{
ERR(("InitDGMA: clGetContextInfo failed (%d)\n", clrc));
goto andOut;
}
sz /= sizeof(cl_device_id);
for (ndx2 = 0; ndx2 < sz; ndx2++)
{
clrc = clGetDeviceInfo(did[ndx2], CL_DEVICE_VENDOR, MAX_PROP_SZ, buff, NULL);
if (CL_SUCCESS != clrc)
{
ERR(("InitDGMA: clGetDeviceInfo %d failed\n", ndx));
goto andOut;
}
if (0 == strcmp(AMD_STR, buff))
{
count += 1; /* another AMD device */
if (count == sNdx2)
{
goto gotThisAMDdevice;
}
}
}
ERR(("InitDGMA: found %d AMD devs in context but index is %d\n", count, sNdx2));
goto andOut;
gotThisAMDdevice:
/*
** OK, we have the device: open a channel
*/
#if USE_OLD_WQ == 0
properties = 0;
sCommandQueue = clCreateCommandQueueWithProperties(sContext, did[ndx2], &properties, &clrc);
if ((NULL == sCommandQueue) || (CL_SUCCESS != clrc))
{
ERR(("InitDGMA: failed to create command queue (%d)\n", 0));
goto andOut;
}
#else
sCommandQueue = clCreateCommandQueue(sContext, did[ndx2], 0, &clrc);
if ((NULL == sCommandQueue) || (CL_SUCCESS != clrc))
{
ERR(("InitDGMA: failed to create command queue (%d)\n", clrc));
goto andOut;
}
#endif
/*
** Create the buffers
*/
sBufs = (cl_mem *) malloc(sNframes * sizeof(cl_mem));
if (NULL == sBufs)
{
ERR(("InitDGMA: failed to get buff list\n"));
goto andOut;
}
(void)memset(sBufs, '\0', (sNframes * sizeof(cl_mem)));
for (i = 0; i < sNframes; i++)
{
sBufs[i] = clCreateBuffer(sContext, CL_MEM_BUS_ADDRESSABLE_AMD, roundSize, NULL, &clrc);
if ((NULL == sBufs[i]) || (CL_SUCCESS != clrc))
{
ERR(("InitDGMA: failed to get %d buff (%d)\n", i, clrc));
goto andOut;
}
}
/*
** And some CPU side store for the frame.
*/
i = frameSize + sPageSize - 1;
i /= sPageSize;
i *= sPageSize;
sOutRAM = malloc(i);
if (NULL == sOutRAM)
{
ERR(("InitDGMA: failed to get RAM store\n"));
goto andOut;
}
sOut = clCreateBuffer(sContext, CL_MEM_USE_HOST_PTR, i, sOutRAM, &clrc);
if ((NULL == sOut) || (CL_SUCCESS != clrc))
{
ERR(("InitDGMA: failed to get out buff (%d)\n", clrc));
goto andOut;
}
DB(("we have buffers\n"));
/*
** Now get the PCI bus address info
*/
sDMAaddrs = (cl_bus_address_amd *) malloc(sNframes * sizeof(cl_bus_address_amd))
if (NULL == sDMAaddrs)
{
ERR(("InitDGMA: failed to get DMA address list\n"));
goto andOut;
}
clrc = (*(sMakeBuffersResidentAMD)) (sCommandQueue, sNframes, sBufs, CL_TRUE, sDMAaddrs, 0, NULL, NULL);
if (CL_SUCCESS != clrc)
{
ERR(("InitDGMA: failed to get physical addresses (%d)\n", clrc));
goto andOut;
}
DB(("we have PCI info\n"));
/*
** We are done.
*/
rc = 0; /* success */
andOut:
if (NULL != oclPlatforms)
{
free(oclPlatforms);
}
/*
** Do any error cleanup.
*/
if (0 != rc)
{
TermDGMA();
}
return (rc);
}
#ifdef DO_SHOW_LIB_DEBUG
/*--------------------------------------------------------------------------*/
static void LDBdisplay(char *format, ...)
/*
** Library debug display function.
**
** This will display progress/information/error strings from BFciLib
*/
{
va_list val;
char buff[8192];
va_start(val, format);
(void)vsprintf(buff, format, val);
va_end(val);
/*
** buff now contains the library display string
**
** This function simply prints it to the console.
*/
(void)printf("LDB: %s\n", buff);
(void)fflush(stdout);
}
#endif
/*--------------------------------------------------------------------------*/
static void InitAndGetDataUntilKeyPress(void)
/*
** Illustrate a simple example VFG interaction sequence.
*/
{
cl_int clrc;
cl_event event;
tCIRC circ;
tCIDOUBLE a = -1.0, b, c, d;
tCIU64 totalBytes = 0, totalLines = 0, *pciAddrs = NULL;
tCIU32 i;
tCIU32 nPtrs;
tCIU8 **uPtrs = NULL;
tCIU8 *p8;
unsigned short *p16;
tCIU32 *p32;
tCIU32 frameID, value, value2, value3, pixToShow;
tCIU8 *frameP;
tCIU32 nFrames, bitsPerPix, hROIoffset, hROIsize, vROIoffset, vROIsize, stride, fsz;
/*
** Open the ndx'th frame grabber with exclusive write permission.
**
** We need exclusive write because GDMA is a case of user scatter-gather
** DMA buffer definition.
*/
circ = CiVFGopen(sNdx, kCIBO_exclusiveWrAccess, &sCIp);
if (kCIEnoErr != circ)
{
ERR(("CiVFGopen gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
return;
}
#ifdef DO_SHOW_LIB_DEBUG
circ = CiSetDebug(sCIp, -1, LDBdisplay);
if (kCIEnoErr != circ)
{
ERR(("CiSetDebug of %d gave '%s'\n", i, CiErrStr(circ)));
}
#endif
/*
** Init the VFG with the config file specified by the DIP switches.
*/
circ = CiVFGinitialize(sCIp, NULL);
if (kCIEnoErr != circ)
{
ERR(("CiVFGinitialize gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** Configure the VFG (temporarily) for 4 frame buffers.
*/
circ = CiDrvrBuffConfigure(sCIp, 0, 0, 0, 0, 0);
if (kCIEnoErr != circ)
{
ERR(("CiDrvrBuffConfigure (1) gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
circ = CiDrvrBuffConfigure(sCIp, 4, 0, 0, 0, 0);
if (kCIEnoErr != circ)
{
ERR(("CiDrvrBuffConfigure (2) gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** Determine buffer configuration.
*/
circ = CiBufferInterrogate(sCIp, &nFrames, &bitsPerPix, &hROIoffset, &hROIsize, &vROIoffset, &vROIsize, &stride);
if (kCIEnoErr != circ)
{
ERR(("CiBufferInterrogate gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** Now release the driver buffers.
*/
circ = CiDrvrBuffConfigure(sCIp, 0, 0, 0, 0, 0);
if (kCIEnoErr != circ)
{
ERR(("CiDrvrBuffConfigure(3) gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** We now know the frame information: initialize DMA buffers on the GPU
*/
fsz = stride * vROIsize;
if (0 != InitDGMA(fsz))
{
ERR(("InitDGMA failed\n"));
sExitAns = 1;
goto andOut;
}
/*
** OK, now we have the info to configure for DMA buffers on the GPU
**
** Build the array of PCI addresses
*/
pciAddrs = (tCIU64 *) malloc(sNframes * sizeof(tCIU64));
if (NULL == pciAddrs)
{
ERR(("could not get PCI address buffer\n"));
sExitAns = 1;
goto andOut;
}
for (i = 0; i < sNframes; i++)
{
pciAddrs[i] = sDMAaddrs[i].surface_bus_address;
/*
** Be sure to align -- extra space was allotted for this.
*/
pciAddrs[i] = (pciAddrs[i] + (sPageSize - 1)) & ((tCIU64) (~(sPageSize - 1)));
}
circ = CiDGMAbuffConfigure(sCIp, sNframes, pciAddrs, stride * vROIsize, 0, 0, 0, 0);
if (kCIEnoErr != circ)
{
ERR(("CiDGMAbuffConfigure(2) gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** This is a necessary step to promote the VFG state. However, the
** returned buffer pointers are invalid.
*/
circ = CiMapFrameBuffers(sCIp, 0, &nPtrs, &uPtrs);
if (kCIEnoErr != circ)
{
ERR(("CiMapFrameBuffers gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** Decide how many per line we show.
*/
switch (bitsPerPix)
{
case 64:
case 8:
pixToShow = 16;
break;
case 10:
case 12:
pixToShow = 12;
break;
case 14:
case 16:
case 24:
pixToShow = 8;
break;
case 30:
case 32:
case 36:
case 48:
pixToShow = 6;
break;
default:
ERR(("Do not know pixBitDepth of %d\n", bitsPerPix));
sExitAns = 1;
goto andOut;
}
/*
** Reset acquisition and clear all error conditions.
*/
circ = CiAqSWreset(sCIp);
if (kCIEnoErr != circ)
{
ERR(("CiAqSWreset gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** Tell the user how to stop this cleanly.
*/
if (0 == sBGok)
{
SHOW(("Will now dump first line of frames until newline (skip %d, ndx %d)\n", sSkipFrames, sNdx));
}
else
{
SHOW(("Will now dump first line of frames until %d (skip %d, ndx %d)\n", sMaxFrames, sSkipFrames, sNdx));
}
/*
** Start continuous acquisition.
*/
circ = CiAqStart(sCIp, 0);
if (kCIEnoErr != circ)
{
ERR(("CiAqStart gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
a = GetTime();
/*
** Display each acquired frame 1st line in a loop. Stop at newline.
*/
while (1)
{
/*
** Check to see if a frame is already available before waiting.
*/
checkAgain:
circ = CiGetOldestNotDeliveredFrame(sCIp, &frameID, &frameP);
switch (circ)
{
case kCIEnoErr:
/*
** We have the frame.
*/
break;
case kCIEnoNewData:
/*
** We need to wait for another frame.
*/
circ = CiWaitNextUndeliveredFrame(sCIp, -1);
if (kCIEnoErr != circ)
{
switch (circ)
{
case kCIEaqAbortedErr:
SHOW(("CiWaitNextUndeliveredFrame gave '%s'\n", CiErrStr(circ)));
break;
default:
ERR(("CiWaitNextUndeliveredFrame gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
}
goto andOut;
}
goto checkAgain;
case kCIEaqAbortedErr:
SHOW(("CiGetOldestNotDeliveredFrame: acqistion aborted\n"));
goto andOut;
default:
ERR(("CiGetOldestNotDeliveredFrame gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** Allow skipping frames so display is not an issue.
*/
if ((0 != sSkipFrames) && (0 != (sDidFrames % (sSkipFrames + 1))))
{
goto skipHere;
}
/*
** Start a copy from GPU to RAM
*/
(void)memset(&event, '\0', sizeof(event));
clrc = clEnqueueCopyBuffer(sCommandQueue, sBufs[sDidFrames % sNframes], sOut, 0, 0, fsz, 0, NULL, &event);
if (CL_SUCCESS != clrc)
{
ERR(("clEnqueueCopyBuffer gave %d\n", clrc));
sExitAns = 1;
goto andOut;
}
/*
** Block until we get it.
*/
clrc = clWaitForEvents(1, &event);
if (CL_SUCCESS != clrc)
{
ERR(("copy faiiled to wait (%d)\n", clrc));
}
clrc = clReleaseEvent(event);
if (CL_SUCCESS != clrc)
{
ERR(("failed to release event (%d)\n", clrc));
}
/*
** Change the frameP to the single host-side output buffer.
*/
frameP = sOutRAM;
/*
** Display the frameID and the first line of frame data.
*/
SHOW(("frameID %9d:", frameID));
switch (bitsPerPix)
{
case 64:
case 8:
p8 = frameP;
for (i = 0; i < pixToShow; i++)
{
value = *p8++;
SHOW((" %02X", value));
}
break;
case 10:
case 12:
p16 = (tCIU16 *) frameP;
for (i = 0; i < pixToShow; i++)
{
value = *p16++;
SHOW((" %03X", value));
}
break;
case 14:
case 16:
p16 = (tCIU16 *) frameP;
for (i = 0; i < pixToShow; i++)
{
value = *p16++;
SHOW((" %04X", value));
}
break;
case 24:
p8 = (tCIU8 *) frameP;
for (i = 0; i < pixToShow; i++)
{
value = *p8++;
value2 = *p8++;
value3 = *p8++;
SHOW((" %02X.%02X.%02X", value, value2, value3));
}
break;
case 30:
p32 = (tCIU32 *) frameP;
for (i = 0; i < pixToShow; i++)
{
value = *p32++;
value2 = (value >> 10) & 0x3FF;
value3 = (value >> 20) & 0x3FF;
value &= 0x03FF;
SHOW((" %03X.%03X.%03X", value, value2, value3));
}
break;
case 32:
p32 = (tCIU32 *) frameP;
for (i = 0; i < pixToShow; i++)
{
value = *p32++;
SHOW((" %08X", value));
}
break;
case 36:
p16 = (tCIU16 *) frameP;
for (i = 0; i < pixToShow; i++)
{
value = *p16++;
value2 = *p16++;
value3 = *p16++;
SHOW((" %03X.%03X.%03X", value, value2, value3));
}
break;
case 48:
p16 = (tCIU16 *) frameP;
for (i = 0; i < pixToShow; i++)
{
value = *p16++;
value2 = *p16++;
value3 = *p16++;
SHOW((" %04X.%04X.%04X", value, value2, value3));
}
break;
default:
ERR(("Do not know pixBitDepth of %d\n", bitsPerPix));
sExitAns = 1;
goto andOut;
}
SHOW(("\n"));
skipHere:
totalLines += vROIsize;
totalBytes += stride * vROIsize;
sDidFrames += 1;
/*
** Break out of this loop on newline
*/
if (0 == sBGok)
{
if (0 != CheckForKeyboardInput())
{
break;
}
}
/*
** Break out of loop if countdown hits zero
*/
if ((0 != sMaxFrames) && (--sMaxFrames == 0))
{
break;
}
}
andOut:
/*
** We must stop acquisition because we are about to tear down the buffers
*/
circ = CiAqAbort(sCIp);
if (kCIEnoErr != circ)
{
ERR(("CiAqAbort gave '%s'\n", CiErrStr(circ)));
}
/*
** Unmap the frame buffers.
*/
if ((NULL != uPtrs) && (kCIEnoErr != (circ = CiUnmapFrameBuffers(sCIp))))
{
ERR(("CiUnmapFrameBuffers gave '%s'\n", CiErrStr(circ)));
}
/*
** Remove the buffers from the driver
*/
circ = CiDGMAbuffConfigure(sCIp, 0, NULL, 0, 0, 0, 0, 0);
if (kCIEnoErr != circ)
{
ERR(("CiDGMAbuffConfigure(end) gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
}
if (NULL != pciAddrs)
{
free(pciAddrs);
}
/*
** Close the access.
*/
if ((NULL != sCIp) && (kCIEnoErr != (circ = CiVFGclose(sCIp))))
{
ERR(("CiVFGclose gave '%s'\n", CiErrStr(circ)));
}
/*
** Tear down the GDMA stuff
*/
TermDGMA();
/*
** Show data rate
*/
c = b = GetTime() - a;
if ((a < 0.0) || (c < 0.001))
{
a = 0.0;
b = 0.0;
c = 0.0;
d = 0.0;
}
else
{
a = ((tCIDOUBLE) totalBytes) / c;
b = ((tCIDOUBLE) totalLines) / c;
d = ((tCIDOUBLE) sDidFrames) / c;
}
SHOW(("%d: Data rate %.1lf ln/s (%.1lf b/s) (%.1lf FPS) (%.1lf sec) after %d fr\n", sNdx, b, a, d, c, sDidFrames));
return;
}
/*==========================================================================*/
int main(int argc, char **argv)
/*
** Decode command line and acquire/display frames until EOF
*/
{
sArgv0 = *argv;
/*
** We need this.
*/
sPageSize = getpagesize();
if (kCIEnoErr == DecodeArgs(argc, argv))
{
InitAndGetDataUntilKeyPress();
}
return (sExitAns);
}
/*==========================================================================*/
/*
$Log: CIsimpleDGMA.c,v $
Revision 1.7 2020/10/02 23:30:13 steve
CLOCK_MONOTONIC is not always monotonic, so prefer CLOCK_MONOTONIC_RAW.
Revision 1.6 2020/10/02 01:17:23 steve
ftime is deprecated. Use clock_gettime.
Revision 1.5 2017/12/12 11:05:52 steve
Fixes for axn+vivid
Revision 1.4 2017/12/04 21:33:36 steve
Much gn2 isr work; diag work; base options
Revision 1.3 2017/09/29 09:14:01 steve
Now dump all camf
Revision 1.2 2016/07/11 20:02:58 steve
Gn2 xx-2Y/2YE, GPUD, DGMA
Revision 1.1 2016/03/06 23:31:45 steve
Support CXP_usualINit and Axion
*/