FrontPanel API
The FrontPanel application provides a turnkey method to make basic user interaction available to your FPGA hardware. But it is not suitable for all applications, particularly those which require further data processing on the PC side of the interface or when data transfer between the PC and FPGA is required. In these cases, a custom software application is usually a better fit. To this end, Opal Kelly provides the FrontPanel Application Programmer’s Interface (API), a consistent (and in some cases cross-platform) interface to the underlying interface driver layer.
The FrontPanel API contains methods which communicate via the USB or PCIe bridge on the device, but the methods have been specifically designed to interface with FPGA hardware in a manner which is consistent with most hardware designs. The API provides methods to interface directly with the FrontPanel HDL modules such as wires, triggers, and pipes. Because of this abstraction, some flexibility in the hardware interface is sacrificed for a dramatically reduced development cycle (and learning curve!) for connecting your FPGA hardware to your custom software.
The library is written in C++ and is provided as a dynamically-linked library. However, Python, Java, and C# versions of the API are also available and can make FPGA development even faster. Because the Python, Java, and C# APIs are generated automatically from the C++ API, most of the methods are identical and you can use the same API reference for all languages. Further, the methods to communicate with PCIe and USB device are either identical or very similar.
API Reference Guide
The API documentation provided in this User’s Manual gives a general overview of how the FrontPanel API is organized and used. More detailed information about the specific calling methods and parameters can be found in the API Reference Guide.
Samples
Often, the best way to learn how to apply a programming interface is to see examples of its application. We encourage you to go through all of our samples to see how applications can be built with the FrontPanel SDK. If you have problems with your own design, it is a good practice to revisit our samples.
Additionally, we have several bite-sized examples that comprise a brief FrontPanel How-To Guide.
Organization
The FrontPanel API is provided as a dynamically-linked library that you include with your application. The interface to the DLL is C, but a C++ wrapper is provided to make the entire DLL appear as if it were a native C++ class in your application.
The library contains a small number of classes which you then instantiate within your code. The details of the USB or PCIe connection between the FPGA and your PC disappear within the neat confines of the API. These classes are shown in the table below in further detailed in what follows.
| CLASS | DESCRIPTION |
|---|---|
| FrontPanel | This is the base class used to find, configure, and communicate with a FrontPanel-enabled device. The methods in the API are organized into four main groups: Device Interaction, Device Configuration, and FPGA Communication. |
| PLL22150 | This is a container class providing methods and structure used to configure the Cypress 22150 PLL on the XEM3001 and XEM3005. An instance of this class can be created and used to program the on-board PLL or the class can be generated from the EEPROM settings. |
| PLL22393 | This is a container class providing methods and structure used to configure the Cypress 22393 PLL on the XEM6010, XEM3010, and XEM3050. An instance of this class can be created and used to program the on-board PLL or the class can be generated from the EEPROM settings. |
PLL Configuration
Some XEM products have a programmable PLL that can be configured through the API. In many cases, your application will require a single pre-set PLL configuration which can be stored to the on-board EEPROM (not the PLL’s EEPROM). In other cases, you may want to configure the PLL from your software.
Preset PLL Configuration
With a preset PLL configuration, you setup the PLL parameters using the FrontPanel Application. You then store these parameters to the on-board EEPROM for future recall. When you startup your application (and typically before FPGA configuration), you can then configure the PLL from this stored preset using a single command:
dev->LoadDefaultPLLConfiguration();Code language: PHP (php)Software PLL Configuration
You can also use the PLL classes to configure PLL parameters and then load them into the PLL. This allows dynamic PLL configuration from your own software. Software PLL configuration is a bit more complicated and requires more intimate knowledge of how the PLL parameters interoperate. Please refer to the corresponding PLL datasheet for details on the PLL parameters specific to that PLL. Then refer to the API Reference Guide for the methods available to set these parameters.
System Flash (USB 3.0)
Some FrontPanel devices have a non-volatile Flash memory attached to the USB microcontroller that is used for firmware and setting storage as well as user storage. The FrontPanel API includes methods for working with this Flash. The available storage and layout of the Flash is device-dependent. Information for each device is available in the User’s Manual for that device.
FrontPanel API Example Usage
Below is a short code snippet that illustrates how the API might be used in a C++ application. More useful and detailed examples can be found in the Samples folder of the FrontPanel installation.
OpalKelly::FrontPanelPtr dev = OpalKelly::FrontPanelDevices().Open();
dev->LoadDefaultPLLConfiguration();
dev->ConfigureFPGA("mybitfile.bit");
// Obtain the dataport
OpalKelly::FPGADataPortClassic* dataport;
if (dev->GetFPGADataPortClassic(dataport) != okErrorCode::NoError) {
std::cerr << "Failed to get FPGA Data Port Classic.\n";
return;
}
// Set a value on WireIn endpoint 0x00.
dataport->SetWireInValue(0x00, 0x37);
dataport->UpdateWireIns();
// Activate TriggerIn 0x40:0 (clears address pointers).
dataport->ActivateTriggerIn(0x40, 0);
// Send 1024 bytes to PipeIn 0x80.
dataport->WriteToPipeIn(0x80, 1024, buf);
// Read 1024 from PipeOut 0xA0.
dataport->ReadFromPipeOut(0xA0, 1024, buf);
// Read the result from WireOut endpoint 0x20.
dataport->UpdateWireOuts();
result = dataport->GetWireOutValue(0x20);Code language: C++ (cpp)Regarding Device Ownership (Multithread or Multiprocess Access)
In general, once an instance of okCFrontPanel has been opened, that instance “owns” the device. That means that, while the API will allow you to create another instance and communicate with the same device, there are likely going to be problems with doing so.
In situations where you must have multiple threads or processes communicating with the same device, it is better to have a single owner of the device instance and route all calls through that owner.
The exception to this is GetDeviceCount() and the associated calls under Linux and Mac OS X. (This exception does not apply to Windows.) You can call this method at any time (even before opening a device) to determine the number of attached FrontPanel devices and retrieve their model numbers, and serial numbers. You may not retrieve the Device ID string without opening the device and that implies “owning” the device.
Communicating with Multiple Devices
In most cases, your software will communicate with a single attached device attached. However, some applications require simultaneous communication with two or more devices. Multiple-device communication is fully supported by the driver and API but will require special consideration when initializing the communication.
Querying Attached Devices
You can call the method GetDeviceCount() to determine the number of supported devices attached to the bus before opening a specific a specific device. The GetDeviceCount() method also queries the device serial numbers and board types of all the attached devices. This information can then be accessed by calling the methods GetDeviceListSerial() and GetDeviceListModel(), respectively.
Platform-Specific Behavior
Windows, Linux, and Mac OS X behave slightly differently with regards to device enumeration using the FrontPanel API. Under Windows, if any process opens a device, that device will no longer be listed on subsequent calls to GetDeviceCount() from a different process. On the other hand, Linux and Mac OS X will allow the opened device to be enumerated. It is up to the user to assure that two processes are not communicating with the same device as this can lead to data corruption or other failures.
Connecting to a Specific Device
It is expected that you would identify a specific board using the serial number (factory-assigned and not user-mutable) or using the device ID string (user configurable via FrontPanel). A typical process for opening multiple devices would then be:
- Create two instances (call them x and y) of
OpalKelly::FrontPanelPtr. - Create an instance (
devices) ofOpalKelly::FrontPanelDevices. - Call
devices.GetCount()to verify that two boards are connected and to query the serial numbers and other device information. - Call
serX = devices.GetSerial(0)to get the first device’s serial number. - Call
serY = devices.GetSerial(1)to get the second device’s serial number. - Call
x = devices.Open(serX)to open the first device. - Call
y = devices.Open(serY)to open the second device.
Using this procedure, you would then have two instances which point to the two devices in your system. They have also been clearly associated with the specific hardware you specified, so there is no ambiguity.