FrontPanel Application Development

In this tutorial you will use the FrontPanel Application template to create a project and build a simple FrontPanel application. The application uses Typescript, Webpack, and the React user interface development library.

Install Prerequisites

Setup the FrontPanel App Project

Download the application template project found in the Opal Kelly Design Resources repository under Software/Templates/frontpanel-app and copy the project folder to a local workspace directory. This template provides a quick way to get started.

Set the current working directory to the root of the project and install the project dependencies.

npm install

Build the FrontPanel App package. This command will produce a package and place it in an output directory.

npm run pack

Connect a USB cable from the PC to the OpalKelly XEM device and power on the device.

Launch the FrontPanel Platform application, and in the Open dialog navigate to the folder where the FrontPanel App package is generated and select the app.asar file.

The application should load and display the FrontPanel Logo demonstrating that it was loaded successfully. This is a good checkpoint to ensure the project is configured correctly before moving on to the next steps.

Add FrontPanel UI Components

In the project folder, open the src/FrontPanel.tsx file in an code editor. This file defines a React component named FrontPanel that is the root component of the user interface for this design.

Locate the render() function definition for the FrontPanel component.

    render() {
        return (
            <FrontPanelContext
                device={this.props.frontpanel}
                workQueue={this.props.workQueue}>
                <div className="ControlPanel">{/* TODO: Add your FrontPanel controls here */}</div>
            </FrontPanelContext>
        );
    }Code language: JavaScript (javascript)

Add a FrontPanelNumberDisplay component that will be connected to a FrontPanel WireOut Endpoint and a FrontPanelPushButton that will be connected to a WireIn Endpoint. In order to use these components they will need to be imported from the @opalkelly/frontpanel-react-components library.

import { 
    FrontPanel as FrontPanelContext,
    FrontPanelNumberDisplay,
    FrontPanelPushButton,
    NumeralSystem
 } from "@opalkelly/frontpanel-react-components";Code language: JavaScript (javascript)
    render() {
        return (
            <FrontPanelContext
                device={this.props.frontpanel}
                workQueue={this.props.workQueue}>
                <div className="ControlPanel">
                    <FrontPanelNumberDisplay
                        label={{text: "Counter #1", horizontalPosition: "right", verticalPosition: "top"}} 
                        tooltip="Counter #1"
                        fpEndpoint={
                            {epAddress: 0x20,bitOffset: 0}
                        }
                        maximumValue={BigInt(0xff)}
                        numeralSystem={NumeralSystem.Decimal}
                        />
                    <FrontPanelPushButton 
                        label="Reset"
                        tooltip="Reset Counter #1"
                        fpEndpoint={
                            {epAddress: 0x00, bitOffset: 0}
                        }
                        />
                </div>
            </FrontPanelContext>
        );
    }Code language: JavaScript (javascript)

Add Periodic Update Timer

Add a FrontPanelPeriodicUpdateTimer to the FrontPanelState interface. This timer will periodically retrieve the state of all FrontPanel WireOut Endpoints.

import {
    IFrontPanel,
    FrontPanelPeriodicUpdateTimer,
    WorkQueue
} from "@opalkelly/frontpanel-platform-api";Code language: JavaScript (javascript)
export interface FrontPanelState {
    updateTimer: FrontPanelPeriodicUpdateTimer;
}Code language: CSS (css)

Initialize the update timer in the constructor of the FrontPanel component.

class FrontPanel extends Component<FrontPanelProps, FrontPanelState> {    
    constructor(props: FrontPanelProps) {
        super(props);

        this.state = {
            updateTimer: new FrontPanelPeriodicUpdateTimer(this.props.frontpanel, 10)
        };
    }Code language: JavaScript (javascript)

Set the FrontPanelContext to use the update timer as the event source that triggers the child components to update the data they display.

    render() {
        return (
            <FrontPanelContext
                device={this.props.frontpanel}
                workQueue={this.props.workQueue}
                eventSource={this.state.updateTimer}>Code language: JavaScript (javascript)

Set the FrontPanel component to start the timer when it is mounted and stop the timer when it is unmounted.

    // Component Lifecycle Methods
    componentDidMount() {
        this.state.updateTimer.start();
    }

    componentWillUnmount() {
        this.state.updateTimer.stop();
    }Code language: JavaScript (javascript)

Add the Counters Example Bitfile

Locate the counters.bit that is compatible with the Opal Kelly XEM device that will be connected to the PC and copy or move it to the assets folder at the root of the application project.

Open the src/index.tsx file using the code editor and add an import statement that specifies the location of the counters.bit file relative to the source file.

import "../assets/counters.bit";Code language: JavaScript (javascript)

This import statement tells the Webpack bundler to include this file in the application bundle it generates.

Open the App.tsx file using the code editor and set the configurationFilename parameter passed to the initializeDevice() function to counters.bit.

function App() {
    const [frontpanel, setFrontPanel] = React.useState<IFrontPanel>();

    React.useEffect(() => {
        let device: IDevice;

        DeviceWorkQueue.post(async () => {
            try {
                device = await initializeDevice("", "counters.bit");

                const frontpanel = await device.getFPGA().getFrontPanel();

                setFrontPanel(frontpanel);
            }
            catch (error) {
                device?.close();
                console.error(error);
            }
        });Code language: JavaScript (javascript)

Build and Run the Application

npm run pack

Connect a USB cable from the PC to the OpalKelly XEM device and power on the device.

Launch the FrontPanel Platform application, and in the Open dialog navigate to the folder where the FrontPanel App package is generated and select the app.asar file.

The application should run and the current value of Counter #1 should display. Clicking the Reset button should result in restarting the counter at the value zero.