/*****************************************************************************
CIexample.c Source for BitFlow CI lib example program
Sep 28, 2008 CIW/SJT
� Copyright 2008, BitFlow, Inc. All rights reserved.
Tabstops are 4
$Author: steve $
$Date: 2020/10/02 23:30:12 $
$Id: CIexample.c,v 1.42 2020/10/02 23:30:12 steve Exp $
*****************************************************************************/
/*==========================================================================*/
/*
** For access to command line display.
*/
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>
/*
** For checking for keypress
*/
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
/*
** For getting timing information.
*/
#include <time.h>
#include <sys/timeb.h>
/*
** For access to BitFlow camera interface library.
*/
#include "BFciLib.h"
/*==========================================================================*/
static int sExitAns = 0; /* program exit code */
static int sLibDebug = 0; /* enable library display */
static tCIp sCIp = NULL; /* device open token */
static int sNdx = 0; /* device index */
static int sBGok = 0; /* ok to be in background */
static int sNframes = 0; /* number of DMA frames */
static int sSkipFrames = 0; /* skip frames between display */
static int sLines = 1; /* lines to display */
static int sTimeout = -1; /* timeout (mSec) */
static int sDelay = -1; /* delay for, e.g., taskset */
static int sMaxFrames = 0; /* total frames to display */
static int sNoClear = 0; /* do not modify frame lines */
static int sSecondsOA = 0; /* overall timeout */
static int sPixShow = -1; /* size of display */
static int sHiFrameRate = 0; /* high frame rate polling */
static int sNoRule = 0; /* DMA as fast as possible */
/*
** Normal behavior is to use the default config file
*/
static char sCfgFN[1024] = ""; /* CiVFGinitialize() cfg file */
/*--------------------------------------------------------------------------*/
#define SHOW(x) { (void)printf x ; (void)fflush(stdout); }
#define ERR(x) { SHOW(("ERR: ")); SHOW(x); }
/*--------------------------------------------------------------------------*/
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);
}
/*--------------------------------------------------------------------------*/
static char *sArgv0 = NULL;
static void ShowHelp(void)
{
SHOW(("%s of " __DATE__ " at " __TIME__ "\n", sArgv0));
SHOW((" -h display this message and exit\n"));
SHOW((" -i show info on system and exit\n"));
SHOW((" -I show more info on system and exit\n"));
SHOW(("\n"));
SHOW((" -x ndx choose available device ndx (default 0)\n"));
SHOW((" -n nFrames reconfigure buffers for nFrames\n"));
SHOW((" -N set DMA_NO_RULE and ignore OVSTEP\n"));
SHOW((" -D display library debug info ('LDB' prefix)\n"));
SHOW((" -b program is backgrounded (no newline exit)\n"));
SHOW((" -c cfgFN CiVFGinitialize() with this config file\n"));
SHOW((" -s nSkip skip frames between display frames (0 default)\n"));
SHOW((" -l nLines display n lines from each frame (1 default)\n"));
SHOW((" -t mSec timeout when waiting for new data (-1 default)\n"));
SHOW((" -w mSec delay after setup, before start aq (-1 default)\n"));
SHOW((" -W nPixShow show this many pixels (default auto size)\n"));
SHOW((" -T sec timeout overall\n"));
SHOW((" -m maxFrames max frames to display (default infinite)\n"));
SHOW((" -C do not clear each line after display\n"));
SHOW((" -P start acquisition for High Frame Rate Polling\n"));
SHOW(("\n"));
SHOW((" CIexample show access to library display and VFG status\n"));
SHOW((" <noarg || -x || -n || -D>\n"));
SHOW((" initialize frame grabber\n"));
SHOW((" configure DMA\n"));
SHOW((" start continuous acquisition\n"));
SHOW((" wait for frames; display 1st 16 pix of 1st row of frame\n"));
SHOW((" <terminate on newline>\n"));
SHOW(("\n"));
}
/*==========================================================================*/
static void ShowCITDP(const char *str, tCITDP citdp)
/*
** Tool to dump typed data.
**
** This illustrates how to access the tCITDP information.
**
** DO NOT CHANGE ANY OF THE INFORMATION!
*/
{
int x = 0, y;
tCIU32 *ptr;
SHOW(("%s\n", str));
if (NULL == citdp)
{
return;
}
while (citdp[x].descriptor != NULL)
{
SHOW((" %-20s: (%3d) (", citdp[x].descriptor, citdp[x].dataID));
switch (citdp[x].dataType)
{
case kBF_tCIU32:
SHOW(("0x%08X", (*((tCIU32 *) (citdp[x].datap)))));
break;
case kBF_tCIU32_pair:
SHOW(("0x%08X", (((tCIU32 *) (citdp[x].datap)))[0]));
SHOW((" 0x%08X", (((tCIU32 *) (citdp[x].datap)))[1]));
break;
case kBF_tCIDOUBLE:
SHOW(("%.3lf", (*((tCIDOUBLE *) (citdp[x].datap)))));
break;
case kBF_tCISTRZ:
SHOW(("'%s'", (((tCISTRZ) (citdp[x].datap)))));
break;
case kBF_tCIU32_list_pair:
ptr = (tCIU32 *) (citdp[x].datap);
y = *ptr++;
SHOW(("%d:\n", y));
while (y-- > 0)
{
SHOW((" 0x%08X 0x%08X\n", ptr[0], ptr[1]));
ptr += 2;
}
break;
case kBF_tCIU32_tCISTRZ_pair:
SHOW(("0x%08X/'%s'", (*((tCIU32 *) (citdp[x].datap))), (((tCISTRZ) (citdp[x].datap)) + sizeof(tCIU32))));
break;
default:
SHOW(("--err-- do not know %d dataType", citdp[x].dataType));
}
SHOW((")\n"));
x += 1;
}
}
/*--------------------------------------------------------------------------*/
static void GetRegAndProc(int ndx)
/*
** Read all registers and then dump the /proc file for this VFG
*/
{
tCIRC circ;
tCIU32 count, x, y;
char fname[64], line[1024];
FILE *fp;
circ = CiRegGetCount(sCIp, &count);
if (kCIEnoErr != circ)
{
ERR(("CiRegGetCount gave '%s'\n", CiErrStr(circ)));
return;
}
/*
** Read the registers, forcing an update of the /proc info
*/
for (x = 0; x < count; x++)
{
(void)CiRegPeek(sCIp, x, &y);
}
/*
** Read the /proc file
*/
(void)sprintf(fname, "/proc/bitflow%02d", ndx);
fp = fopen(fname, "r");
if (NULL == fp)
{
ERR(("GetRegAndProc: fopen of '%s' gave '%s'\n", fname, CiErrStr(errno)));
return;
}
SHOW(("contents of '%s'\n", fname));
while (NULL != fgets(line, 1024, fp))
{
SHOW(("%s", line));
}
SHOW(("\n"));
(void)fclose(fp);
return;
}
/*--------------------------------------------------------------------------*/
#define CASE_STATE_STR(label) \
case kCIBQ_ ## label : (void)sprintf(str,"%s", #label); break;
#define CASE_AQSTATE_STR(label) \
case kCIAQS ## label : (void)sprintf(str,"%s", #label); break;
static void DoShowInfo(int doAll)
/*
** Query all possible information from all installed frame grabbers.
*/
{
static const char *sBoardNames[kCICT_VFGmask + 1] = {
"--none--", "Neon", "NeonDIF", "Karbon",
"Alta", "KbnCXP (deprecated)", "CtnCXP", "AxnCL",
"AonCXP", "ClxCXP", "ClxFXP", "--none--",
"--none--", "--none--", "--none--", "--none--",
"--none--", "--none--", "--none--", "--none--",
"--none--", "--none--", "--none--", "--none--",
"--none--", "--none--", "--none--", "--none--",
"--none--", "--none--", "--none--", "--none--"
};
tCIRC circ;
tCITDP cfgFN, cfg, camFN, cam, firmFN, firm, serial, cxp, spare;
tCIU32 lv, dv, nb, i, stt, ih = 0, il = 0, node;
tCIU32 ctab[kCIszCTAB];
tCIU32 ift, sw, ndx, db, par, sb, baud;
char name[256], *str, vfg[64], *fmt = NULL;
tCIU32 ic[kCINinterruptCounters];
tCIU32 nf, bpp, h0, hsz, v0, vsz, stride, nerr;
tCIdiagStruct ds;
char hwRev[32];
/*
** Get library/driver version information.
*/
switch (circ = CiSysGetVersions(&lv, &dv))
{
case kCIEnoErr:
SHOW(("CiSysGetVersions: 0x%08X library, 0x%08X driver\n", lv, dv));
break;
case kCIEnoAccessibleVideo:
case kCIEnullArg:
case kCIEversionErr:
default:
ERR(("CiSysGetVersions gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** Get a count of frame grabbers.
*/
circ = CiSysVFGenum(&nb);
if (kCIEnoErr != circ)
{
ERR(("CiSysVFGenum gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
SHOW(("CiSysBrdEnum returns %d frame grabbers installed\n", nb));
/*
** For all frame grabbers: show all information.
*/
for (i = 0; i < nb; i++)
{
/*
** Get basic info about this frame grabber.
*/
circ = CiSysVFGinfo2(i, &ift, &sw, &ndx, name, &ih, &il, vfg, &node);
if (kCIEnoErr != circ)
{
ERR(("CiSysVFGinfo2 of %d gave '%s'\n", i, CiErrStr(circ)));
continue;
}
SHOW((" BitFlow device %d is %s%02d, node %d, type '%s', "
"switches %d, on bus '%s' (%s) (0x%04x 0x%04X '%s')\n",
i, "/dev/video", ndx, node, sBoardNames[ift & kCICT_VFGmask], sw, name,
(0 != (ift & kCICT_isMaster)) ? "master" : "not_master", ih, il, vfg));
/*
** Set library debug function if '-D' was specified.
*/
circ = CiSetDebug(sCIp, -1, (0 == sLibDebug) ? NULL : LDBdisplay);
if (kCIEnoErr != circ)
{
ERR(("CiSetDebug of %d gave '%s'\n", i, CiErrStr(circ)));
}
/*
** Try to open this frame grabber (readWrite in case not flashed)
*/
circ = CiVFGopen(ndx, kCIBO_writeAccess, &sCIp);
switch (circ)
{
case kCIEnoErr:
break;
case kCIEexclusiveFail:
/*
** It's already open exclusiveWrite so it will not need to be
** flashed.
*/
circ = CiVFGopen(ndx, kCIBO_readOnly, &sCIp);
if (kCIEnoErr == circ)
{
break;
}
default:
ERR(("CiVFGopen of %d/%d gave '%s'\n", i, ndx, CiErrStr(circ)));
continue;
}
/*
** Get overall VFG state.
*/
circ = CiVFGqueryState(sCIp, &stt);
if (kCIEnoErr != circ)
{
ERR(("CiVFGqueryState of %d gave '%s'\n", i, CiErrStr(circ)));
goto closeAndNext;
}
str = name;
switch (stt)
{
CASE_STATE_STR(shuttingDown);
CASE_STATE_STR(startingUp);
CASE_STATE_STR(needsFirmware);
CASE_STATE_STR(firmwareLoaded);
CASE_STATE_STR(dmaBufferReady);
CASE_STATE_STR(dmaIsActive);
CASE_STATE_STR(dmaIsAborted);
CASE_STATE_STR(stateUnknown);
default:
(void)sprintf(str, "--%d invalid--", stt);
}
SHOW((" frame grabber %d in %d/%s state\n", i, stt, str));
/*
** If we need firmware then there is no point continuing.
*/
if (kCIBQ_needsFirmware == stt)
{
goto closeAndNext;
}
/*
** Query all possible typed data driver information.
*/
circ = CiVFGinquire2(sCIp, &cfgFN, &cfg, &camFN, &cam, &firmFN, &firm, &serial, &cxp, &spare, &fmt);
if (kCIEnoErr != circ)
{
ERR(("CiVFGinquire of %d gave '%s'\n", i, CiErrStr(circ)));
goto closeAndNext;
}
ShowCITDP("configuration file name", cfgFN);
ShowCITDP("configuration file data", cfg);
ShowCITDP("camera file name", camFN);
ShowCITDP("camera file data", cam);
ShowCITDP("firmware file name", firmFN);
ShowCITDP("firmware file data", firm);
ShowCITDP("CameraLink serial port data", serial);
ShowCITDP("CXP link affinity", cxp);
ShowCITDP("spare", spare);
SHOW(("fmt str: '%s'\n", fmt));
/*
** Display all interrupt count information.
*/
circ = CiGetIntCounts(sCIp, ic);
if (kCIEnoErr != circ)
{
ERR(("CiGetIntCounts of %d gave '%s'\n", i, CiErrStr(circ)));
goto closeAndNext;
}
SHOW(("IntCounts: HW TRIG SER QUAD CTAB EOF OVSTEP CXP TOTAL\n" " %6d %6d %6d %6d %6d %6d %6d %6d %6d\n", ic[0], ic[1], ic[2], ic[3], ic[4], ic[5], ic[6], ic[7], ic[8]));
/*
** Display buffer configuration.
*/
circ = CiBufferInterrogate(sCIp, &nf, &bpp, &h0, &hsz, &v0, &vsz, &stride);
switch (circ)
{
case kCIEnoErr:
SHOW((" %d frames, %d bitsPerPix, %d-%d horizontal, %d-%d vertical, %d stride\n", nf, bpp, h0, hsz, v0, vsz, stride));
break;
case kCIEnotConfigured:
SHOW(("CiBufferInterrogate of %d gave '%s'\n", i, CiErrStr(circ)));
/*
** No point checking furrther.
*/
goto closeAndNext;
default:
ERR(("CiBufferInterrogate of %d gave '%s'\n", i, CiErrStr(circ)));
goto closeAndNext;
}
/*
** Display acquisition status.
*/
circ = CiAqGetStatus(sCIp, &stt, &nf, &nerr);
if (kCIEnoErr != circ)
{
ERR(("CiAqGetStatus of %d gave '%s'\n", i, CiErrStr(circ)));
goto closeAndNext;
}
str = name;
switch (stt & kCIAQSstateMask)
{
CASE_AQSTATE_STR(invalidState);
CASE_AQSTATE_STR(idle);
CASE_AQSTATE_STR(snapShotInProcess);
CASE_AQSTATE_STR(snapShotDone);
CASE_AQSTATE_STR(continuousInProcess);
CASE_AQSTATE_STR(errorDone);
CASE_AQSTATE_STR(continuousStopping);
CASE_AQSTATE_STR(continuousDone);
default:
(void)sprintf(str, "(%d not known) ", (stt & kCIAQSstateMask));
}
if (0 != (stt & (kCIAQSaqIsSIP | kCIAQSaqUnderrun | kCIAQSaqAbort)))
{
(void)sprintf((str + strlen(str)), " (");
}
if (0 != (stt & kCIAQSaqIsSIP))
{
(void)sprintf((str + strlen(str)), " SIP");
}
if (0 != (stt & kCIAQSaqUnderrun))
{
(void)sprintf((str + strlen(str)), " under");
}
if (0 != (stt & kCIAQSaqAbort))
{
(void)sprintf((str + strlen(str)), " abort");
}
if (0 != (stt & (kCIAQSaqIsSIP | kCIAQSaqUnderrun | kCIAQSaqAbort)))
{
(void)sprintf((str + strlen(str)), " )");
}
SHOW((" AqStatus: %s (%d frames collected, %d errs)\n", name, nf, nerr));
/*
** Get a count of available CON registerx.
*/
circ = CiRegGetCount(sCIp, &nf);
if (kCIEnoErr != circ)
{
ERR(("CiRegGetCount of %d gave '%s'\n", i, CiErrStr(circ)));
goto closeAndNext;
}
SHOW((" registers CON0 through CON%d supported\n", nf - 1));
/*
** Display all diagnostic information.
*/
circ = CiGetDiag(sCIp, &ds);
if (kCIEnoErr != circ)
{
ERR(("CiGetDiag of %d gave '%s'\n", i, CiErrStr(circ)));
goto closeAndNext;
}
SHOW(("DiagCounts: aqStat fActiv fCount lCount pCount fenCnt vCount hCount\n" " %08X %6d %6d %6d %6d %6d %6d %6d\n", ds.db.aqStat, ds.db.fActive, ds.db.fCount, ds.db.lCount, ds.db.pCount, ds.db.fenCount, ds.db.vCount, ds.db.hCount));
/*
** Dump the CTABs
*/
circ = CiReadCTABcompressed(sCIp, 0, ctab);
if (kCIEnoErr == circ)
{
SHOW(("H CTAB:\n"));
for (nf = 0; nf < kCIszCTAB; nf++)
{
SHOW((" %2d: 0x%08X\n", nf, ctab[nf]));
}
}
circ = CiReadCTABcompressed(sCIp, 1, ctab);
if (kCIEnoErr == circ)
{
SHOW(("V CTAB:\n"));
for (nf = 0; nf < kCIszCTAB; nf++)
{
SHOW((" %2d: 0x%08X\n", nf, ctab[nf]));
}
}
/*
** Finally, show any available CameraLink information.
*/
circ = CiCLinfo(sCIp, &db, &par, &sb, &baud);
switch (circ)
{
case kCIEnoErr:
SHOW((" CameraLink: %d dataBits, %d parity, %d stopBits, %d baud\n", db, par, sb, baud));
break;
case kCIEnotOpen:
SHOW((" CameraLink: not open\n"));
break;
case kCIEnotSupported:
SHOW((" CameraLink not supported on hardware\n"));
break;
default:
ERR(("CiCLinfo of %d gave '%s'\n", i, CiErrStr(circ)));
goto closeAndNext;
}
closeAndNext:
/*
** Try for HW rev -- only good on Karbon master
*/
if (kCIEnoErr == CiReadHWrev(sCIp, hwRev))
{
SHOW((" hwRev is '%s'\n", hwRev));
}
else
{
SHOW((" hwRev not available\n"));
}
/*
** Try for serial number
*/
if (kCIEnoErr == CiReadSerialNo(sCIp, hwRev))
{
SHOW((" serNo is '%s'\n", hwRev));
}
else
{
SHOW((" serNo not available\n"));
}
/*
** Deal with registers and /proc
*/
if (0 != doAll)
{
GetRegAndProc(ndx);
}
/*
** Close access to this frame grabber.
*/
if ((NULL != sCIp) && (kCIEnoErr != (circ = CiVFGclose(sCIp))))
{
ERR(("CiVFGclose of %d gave '%s'\n", i, CiErrStr(circ)));
}
sCIp = NULL;
}
andOut:
/*
** Cleanly close access on error.
*/
if ((NULL != sCIp) && (kCIEnoErr != (circ = CiVFGclose(sCIp))))
{
ERR(("CiVFGclose gave '%s'\n", CiErrStr(circ)));
}
return;
}
/*--------------------------------------------------------------------------*/
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();
sExitAns = 1;
return (sExitAns);
}
switch (str[1])
{
case 'h':
ShowHelp();
return (1);
case 'i':
DoShowInfo(0);
return (1);
case 'I':
DoShowInfo(1);
return (1);
case 'D':
sLibDebug = 1;
break;
case 'x':
(void)sscanf(*argv, "%d", &sNdx);
argv += 1;
argc -= 1;
break;
case 'm':
(void)sscanf(*argv, "%d", &sMaxFrames);
argv += 1;
argc -= 1;
break;
case 'C':
sNoClear = 1;
break;
case 'P':
sHiFrameRate = 1;
break;
case 'b':
sBGok = 1;
break;
case 'c':
(void)strcpy(sCfgFN, *argv);
argv += 1;
argc -= 1;
break;
case 'n':
(void)sscanf(*argv, "%d", &sNframes);
argv += 1;
argc -= 1;
break;
case 's':
(void)sscanf(*argv, "%d", &sSkipFrames);
argv += 1;
argc -= 1;
break;
case 'l':
(void)sscanf(*argv, "%d", &sLines);
argv += 1;
argc -= 1;
break;
case 'W':
(void)sscanf(*argv, "%d", &sPixShow);
argv += 1;
argc -= 1;
break;
case 'w':
(void)sscanf(*argv, "%d", &sDelay);
argv += 1;
argc -= 1;
break;
case 't':
(void)sscanf(*argv, "%d", &sTimeout);
argv += 1;
argc -= 1;
break;
case 'T':
(void)sscanf(*argv, "%d", &sSecondsOA);
argv += 1;
argc -= 1;
break;
case 'N':
sNoRule = 1;
break;
default:
ERR(("Do not know arg '%s' arg\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 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 void InitAndGetDataUntilKeyPress(void)
/*
** Illustrate a simple exampler board interaction sequence.
*/
{
tCIRC circ;
char buff[256], *str;
tCIU32 n, i, j;
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;
tCIU32 totalFrames = 0, bytesPerFrame = 0;
tCIDOUBLE before = 0.0, after = 0.0, bps, fps;
tCIextraFrameInfo xi;
tCIU32 ic[kCINinterruptCounters];
(void)memset(ic, '\0', sizeof(ic));
/*
** Set library debug function if '-D' was specified.
*/
circ = CiSetDebug(sCIp, -1, (0 == sLibDebug) ? NULL : LDBdisplay);
if (kCIEnoErr != circ)
{
ERR(("CiSetDebug gave '%s'\n", CiErrStr(circ)));
}
/*
** Open the ndx'th frame grabber with write permission.
*/
circ = CiVFGopen(sNdx, kCIBO_writeAccess, &sCIp);
if (kCIEnoErr != circ)
{
ERR(("CiVFGopen gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
return;
}
/*
** Get and display the state of the frame grabber.
*/
circ = CiVFGqueryState(sCIp, &n);
if (kCIEnoErr != circ)
{
ERR(("CiVFGqueryState gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
str = buff;
switch (n)
{
CASE_STATE_STR(shuttingDown);
CASE_STATE_STR(startingUp);
CASE_STATE_STR(needsFirmware);
CASE_STATE_STR(firmwareLoaded);
CASE_STATE_STR(dmaBufferReady);
CASE_STATE_STR(dmaIsActive);
CASE_STATE_STR(stateUnknown);
default:
(void)sprintf(str, "--%d invalid--", n);
}
/*
** Initialize the VFG, possibly with a custom config file.
*/
circ = CiVFGinitialize(sCIp, sCfgFN);
if (kCIEnoErr != circ)
{
ERR(("CiVFGinitialize gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** If nFrames specified on command line then reconfigure the buffers.
*/
if ((0 != sNframes) && (kCIEnoErr != (circ = CiDrvrBuffConfigure(sCIp, sNframes, 0, 0, 0, 0))))
{
ERR(("CiDrvrBuffConfigure 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;
}
SHOW((" %d frames, %d bitsPerPix, %d-%d horizontal, %d-%d vertical, %d stride\n", nFrames, bitsPerPix, hROIoffset, hROIsize, vROIoffset, vROIsize, stride));
bytesPerFrame = stride * vROIsize;
/*
** Test for condition we know will cause data errors: continuous
** acquisition into a single buffer.
*/
if (2 > nFrames)
{
SHOW(("WARNING: %d frames inadequate for continuous acquisition!\n", nFrames));
}
/*
** Get the buffer pointers for read/write access to buffers.
*/
circ = CiMapFrameBuffers(sCIp, 1, &nPtrs, &uPtrs);
if (kCIEnoErr != circ)
{
ERR(("CiMapFrameBuffers gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** Reset acquisition.
*/
circ = CiAqSWreset(sCIp);
if (kCIEnoErr != circ)
{
ERR(("CiAqSWreset gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** Clear the first line(s) of all buffers.
*/
for (i = 0; i < nPtrs; i++)
{
(void)memset(uPtrs[i], '\0', stride * sLines);
}
/*
** 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;
}
if (0 < sPixShow)
{
pixToShow = sPixShow;
}
/*
** Tell the user how to stop this cleanly.
*/
if (0 == sBGok)
{
if (0 == sMaxFrames)
{
SHOW(("%d Will dump first line of frames until newline (skip %d, ndx %d, %d nc, %d hfr)\n", ((int)(getpid())), sSkipFrames, sNdx, sNoClear, sHiFrameRate));
}
else
{
SHOW(("%d Will dump first line of frames until newline or %d (skip %d, ndx %d, %d nc, %d hfr)\n", ((int)(getpid())), sMaxFrames, sSkipFrames, sNdx, sNoClear, sHiFrameRate));
}
}
else
{
SHOW(("%d Will dump first line of frames until %d (skip %d, ndx %d, %d nc, %d hfr)\n", ((int)(getpid())), sMaxFrames, sSkipFrames, sNdx, sNoClear, sHiFrameRate));
}
/*
** Delay for, e.g., taskset, trigger setup, etc.
*/
if (0 < sDelay)
{
usleep(sDelay * 1000);
SHOW((" after %.3lf sec\n", (((double)(sDelay * 1000)) / (1000000.0))));
}
/*
** Start continuous acquisition.
*/
if (sHiFrameRate == 0)
{
circ = CiAqStart(sCIp, 0);
if (kCIEnoErr != circ)
{
ERR(("CiAqStart gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
}
else
{
circ = CiAqStartHiFrameRate(sCIp, 0);
if (kCIEnoErr != circ)
{
ERR(("CiAqStartHiFrameRate gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
}
if (0 != sNoRule)
{
/*
** Turn off INT_OVSTEP: must be done _after_ CiAqStart()
*/
SHOW((" using DMA_NO_RULE logic\n"));
circ = CiFieldPoke(sCIp, CiFieldNdxFromStr(sCIp, (char *)"ENINT_OVSTEP"), 0);
if (kCIEnoErr != circ)
{
ERR(("CiFieldPoke (ENINT_OVSTEP) gave %s\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** Set DMA_NO_RULE: WARNING! register modification is persistent!
*/
circ = CiFieldPoke(sCIp, CiFieldNdxFromStr(sCIp, (char *)"DMA_NO_RULE"), 1);
if (kCIEnoErr != circ)
{
ERR(("CiFieldPoke (DMA_NO_RULE) gave %s\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
}
/*
** Display each acquired frame 1st line in a loop. Stop at newline.
*/
before = GetTime(); /* mark acquisition start */
do
{
/*
** 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, sTimeout);
if (kCIEnoErr != circ)
{
switch (circ)
{
case kCIEaqAbortedErr:
SHOW(("CiWaitNextUndeliveredFrame gave '%s' at %d\n", CiErrStr(circ), totalFrames));
break;
default:
ERR(("CiWaitNextUndeliveredFrame gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
}
goto andOut;
}
goto checkAgain;
case kCIEaqAbortedErr:
SHOW(("CiGetOldestNotDeliveredFrame: aquisition was aborted\n"));
goto andOut;
default:
ERR(("CiGetOldestNotDeliveredFrame gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
totalFrames += 1; /* another frame */
/*
** If DMA_NORULE then do not attempt to display each frame; every
** 100th should do fine.
*/
if ((0 != sNoRule) && (0 != (totalFrames % 100)))
{
goto noDisplay;
}
/*
** And allow skipping on other conditions.
*/
if ((0 != sSkipFrames) && (0 != (totalFrames % (sSkipFrames + 1))))
{
goto noDisplay;
}
/*
** If not DMA_NORULE then get the timestamp.
*/
xi.frameID = frameID;
if (0 != sNoRule)
{
xi.timestamp = 0;
}
else if (kCIEnoErr != (circ = CiGetExtraFrameInfo(sCIp, sizeof(xi), &xi)))
{
ERR(("CiGetExtraFrameInfo gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
/*
** Display the frameID and the first line of frame data.
*/
for (j = 0; j < sLines; j++)
{
SHOW(("frameID %6d(%1d)(%Ld):", frameID, j, (tCIU64) xi.timestamp));
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"));
/*
** We need to be able to cooperate w/CIcmdln showUnchanged
*/
if (0 == sNoClear)
{
/*
** Clear this line so we know when it is rewritten.
*/
(void)memset(frameP, '\0', stride);
}
/*
** End of line loop: advance frame pointer.
*/
frameP += stride;
}
noDisplay:
/*
** Break out of loop on newline
*/
if (0 == sBGok)
{
if (0 != CheckForKeyboardInput())
{
break;
}
}
/*
** Break out of loop if countdown hits zero
*/
if ((0 != sMaxFrames) && (--sMaxFrames == 0))
{
break;
}
}
while ((sSecondsOA == 0) ||
/*
** Break out if nothing happens.
*/
(GetTime() < (before + ((tCIDOUBLE) (sSecondsOA)))));
#ifdef STOP_AQ
#warning "STOP_AQ is set"
/*
** Abort acquisition.
*/
circ = CiAqAbort(sCIp);
if (kCIEnoErr != circ)
{
ERR(("CiAqStop gave '%s'\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut;
}
#endif
/*
** Here is a good place to see how many frames are still waiting...
*/
circ = CiGetIntCounts(sCIp, ic);
if (kCIEnoErr != circ)
{
ERR(("CiGetIntCounts of %d gave '%s'\n", i, CiErrStr(circ)));
goto andOut;
}
andOut:
after = GetTime(); /* mark acquisition end */
#ifdef STOP_AQ
#warning "STOP_AQ is set"
/*
** Reset acquisition.
*/
circ = CiAqSWreset(sCIp);
if (kCIEnoErr != circ)
{
ERR(("CiAqSWreset gave '%s'\n", CiErrStr(circ)));
}
#endif
/*
** Unmap the frame buffers.
*/
if ((NULL != uPtrs) && (kCIEnoErr != (circ = CiUnmapFrameBuffers(sCIp))))
{
ERR(("CiUnmapFrameBuffers gave '%s'\n", CiErrStr(circ)));
}
/*
** Avoid hassles.
*/
if (0 != sNoRule)
{
circ = CiFieldPoke(sCIp, CiFieldNdxFromStr(sCIp, (char *)"DMA_NO_RULE"), 0);
if (kCIEnoErr != circ)
{
ERR(("CiFieldPoke (DMA_NO_RULE) gave %s\n", CiErrStr(circ)));
sExitAns = 1;
goto andOut2;
}
SHOW((" DMA_NO_RULE reset to 0\n"));
}
andOut2:
/*
** Display data rate, ususally determined by the EOF count, but
** determined by the QUAD count when DMA_NO_RULE is set.
*/
bps = bytesPerFrame;
bps *= totalFrames;
if (after == before)
{
bps = 0.0;
fps = 0.0;
}
else
{
bps = bps / (after - before);
fps = totalFrames;
fps /= after - before;
}
if ((sSecondsOA > 0.0) && (GetTime() >= (before + ((tCIDOUBLE) (sSecondsOA)))))
{
str = (char *)"timeout";
}
else
{
str = (char *)"";
}
SHOW(("%d had %d(%d) frames of %d bytes, %.3f bytes/sec (%.1lf FPS(%s))\n", sNdx, totalFrames, ((ic[kCIintCountEOF] == 0) ? (0) : (ic[kCIintCountEOF] - totalFrames)), bytesPerFrame, (tCIDOUBLE) bps, fps, str));
/*
** Close the access.
*/
if ((NULL != sCIp) && (kCIEnoErr != (circ = CiVFGclose(sCIp))))
{
ERR(("CiVFGclose gave '%s'\n", CiErrStr(circ)));
}
return;
}
/*==========================================================================*/
int main(int argc, char **argv)
/*
** Decode command line and (usually) acquire/display frames until EOF
*/
{
sArgv0 = *argv;
if (kCIEnoErr == DecodeArgs(argc, argv))
{
if (0 == sMaxFrames)
{
SHOW(("main: will init and get data until newline\n"));
}
else
{
SHOW(("main: will init and get data for %d frames\n", sMaxFrames));
}
InitAndGetDataUntilKeyPress();
}
return (sExitAns);
}
/*==========================================================================*/
/*
$Log: CIexample.c,v $
Revision 1.42 2020/10/02 23:30:12 steve
CLOCK_MONOTONIC is not always monotonic, so prefer CLOCK_MONOTONIC_RAW.
Revision 1.41 2020/10/02 01:17:22 steve
ftime is deprecated. Use clock_gettime.
Revision 1.40 2020/09/02 23:53:05 steve
Deprecate Karbon CXP, add Claxon.
Revision 1.39 2019/04/29 21:34:43 steve
Improvements to CiAqStartHiFrameRate integration.
Revision 1.38 2019/04/27 00:00:19 steve
Added -H flag to enable High Frame Rate Polling
Revision 1.37 2017/12/12 11:05:51 steve
Fixes for axn+vivid
Revision 1.36 2017/12/04 21:33:36 steve
Much gn2 isr work; diag work; base options
Revision 1.35 2017/09/29 09:14:00 steve
Now dump all camf
Revision 1.34 2016/07/11 20:02:56 steve
Gn2 xx-2Y/2YE, GPUD, DGMA
Revision 1.33 2016/03/06 23:16:08 steve
Support CXP_usualInit and support Axion
Revision 1.32 2015/06/23 17:11:03 steve
Ready for ndif and cxp2
Revision 1.31 2015-01-26 13:06:18 steve
Final 9.02
Revision 1.30 2015-01-24 19:35:52 steve
Almost done
Revision 1.29 2015-01-15 17:24:40 steve
Cyton available
Revision 1.28 2014-06-09 10:49:26 steve
Address release test errs
Revision 1.27 2014-05-29 13:14:14 steve
User lib c++ supporting Neon/Alta/Kbn/KbnCXP
Revision 1.26 2014-03-18 02:22:14 steve
Fix err msg
Revision 1.25 2014-03-15 20:57:28 steve
Reorg for c++, SDK 9.00
Revision 1.24 2013-03-03 18:58:11 steve
Ready w/CXP
Revision 1.23 2012-11-20 00:43:13 steve
Fixed CCx_CON issue w/ISR
Revision 1.22 2012-09-14 14:25:56 steve
CiSetDebugCL(), CON51, fix sscanf(), cust kern dir
Revision 1.21 2012-06-01 00:14:19 steve
Final on 8.10
Revision 1.20 2012-04-27 21:15:32 steve
Fix CONFIG_X86_NOPAT, doc iommu, add CIsimpleSG
Revision 1.19 2012-02-10 02:41:14 steve
Fix more details
Revision 1.18 2012-02-10 01:02:29 steve
Fix typo
Revision 1.17 2012-02-10 00:52:53 steve
Fix some tests
Revision 1.16 2011-05-17 21:55:57 steve
Fix details.
Revision 1.15 2011-05-16 21:44:18 steve
Demote aq abort from err.
Revision 1.14 2011-05-16 21:11:15 steve
Faster serial out. Abort wakes all sleepers.
Revision 1.13 2011-03-27 16:01:37 steve
Minimize SIP restart time
Revision 1.12 2011-02-18 17:07:02 steve
Fixed CB/SIP, DPM test, added slow test cam
Revision 1.11 2011-02-14 04:10:05 steve
Karbon, SIP, DMA fixes
Revision 1.10 2011-01-05 19:00:04 steve
Ignore buffID err on norule. Also tweak DMAboundary test
Revision 1.9 2011-01-03 19:30:25 steve
SIP lines, TSC, bugfix CCn, cb nolog err
Revision 1.8 2010-06-03 14:34:29 steve
Added DAM/SG diagnostics to CIcmdln.
Revision 1.7 2010-02-24 21:21:09 steve
v706 candidate w/SIP
Revision 1.6 2009-06-18 13:37:54 steve
Full ROI, s-g DMA, flush CL, Kbn flash delay
Revision 1.5 2009-01-24 17:54:00 steve
CIexample has DMA_NO_RULE benchmark
Revision 1.4 2009-01-22 11:38:53 steve
User-alloc DMA; full ROI; register fields
Revision 1.3 2008-10-16 02:50:32 steve
Beta2: now have .so library.
Revision 1.2 2008-10-08 18:13:49 steve
Release test ready.
Revision 1.1 2008-09-29 06:41:14 steve
CIexample now exists. Version pumped.
*/