A DMA transfer can be continuous or noncontinuous:
For portability, use the library calls edt_reg_read, edt_reg_write, edt_reg_or, or edt_reg_and to read or write the hardware registers, rather than using ioctls.
By default, EDT's pcd installation package is copied into c: (Windows), or /opt/EDTpdv (Linux / Macos). For pdv packages, see the EDT Digital Imaging Library.
nmake
application that comes with Visual Studio, or the Unix make
utility, as described below.1. Do one of the following:
c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat amd64
c:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\vcvarsall.bat x86
2. Enter
make file
make
includes.mk
and makefile.def
for lists of the library objects (which all have .c source files), applications, and header files.
Applications that perform continuous transfers typically include the following elements:
#include "edtinc.h"
Example
#include "edtinc.h" main() { EdtDev *edt_p = edt_open("pcd", 0) ; char *buf_ptr; int outfd = open("outfile", 1) ; // Configure a ring buffer with four 1MB buffers edt_configure_ring_buffers(edt_p, 1024*1024, 4, EDT_READ, NULL) ; edt_start_buffers(edt_p, 0) ; // 0 starts unlimited buffer DMA // This loop will capture data indefinitely, but the write() (or // other data processing) must be able to keep up. while ((buf_ptr = edt_wait_for_buffers(edt_p, 1)) != NULL) write(outfd, buf_ptr, 1024*1024) ; edt_close(edt_p) ; }
Applications that perform noncontinuous transfers typically include the following elements:
#include "edtinc.h"
Assuming that a multichannel FPGA configuration file has been loaded, this example opens a specific DMA channel with edt_open_channel:
#include "edtinc.h" main() { EdtDev *edt_p = edt_open_channel("pcd", 1, 2) ; char buf[1024] ; int numbytes, outfd = open("outfile", 1) ; // Because read()s are noncontinuous, without hardware // handshaking, the data will have gaps between each read(). while ((numbytes = edt_read(edt_p, buf, 1024)) > 0) write(outfd, buf, numbytes) ; edt_close(edt_p) ; }
You can use ring buffer mode for real-time data capture using a small number of buffers (typically 1 MB) configured in a round-robin data FIFO. During capture, the application must be able to transfer or process the data before data acquisition wraps around and overwrites the buffer currently being processed. The example below shows real-time data capture using ring buffers, although it includes no error-checking. In this example, process_data(bufptr)
must execute in the same amount of time it takes DMA to fill a single buffer, or faster.
#include "edtinc.h" main() { EdtDev *edt_p = edt_open("pcd", 0) ; // Configure four 1 MB buffers: // one for DMA // one for the second DMA register on most EDT boards // one for "process_data(bufptr)" to work on // one to keep DMA away from "process_data()" // edt_configure_ring_buffers(edt_p, 0x100000, 4, EDT_READ, NULL) ; edt_start_buffers(edt_p, 0) ; // 0 starts unlimited buffer DMA for (;;) { char *bufptr ; // Wait for each buffer to complete, then process it. // The driver continues DMA concurrently with processing. // bufptr = edt_wait_for_buffers(edt_p, 1) ; process_data(bufptr) ; } }
Check compiler options in the EDT-provided makefiles.
The EDT driver is thread-safe, with the following constraints:
Modules | |
Startup / Shutdown | |
These functions are used to open and close the EDT device. | |
Initialization | |
FIFO Flushing | |
First-in, first-out (FIFO) memory buffers are used to smooth data transmission between different types of data sinks internal to EDT boards. | |
Input/Output | |
These functions are used to perform and control DMA transfers. | |
Register Access | |
Register access functions. | |
Utility | |
Utility functions. |