Polling Device State
Starting from the template project built using the steps from the Building the Template App guide, this guide will explain how the template application periodically retrieves the current value of the counter and displays it in the text field seen in the application.
Install Prerequisites
- Build the Template App – Building the Template App
Periodic Update Timer
In the project folder open the src/FrontPanel.tsx
file in an code editor and locate the FrontPanel
component function.
This component is responsible for retrieving the current value of the counter by calling getWireOutValue()
and storing that value in its state at regular intervals. It accomplishes this with the help of the FPGADataPortClassicPeriodicUpdateTimer
provided in the FrontPanel API Library.
The FrontPanel component in the template creates the update timer and subscribes to update events when it initializes.
React.useEffect(() => {
const updateTimer = new FPGADataPortClassicPeriodicUpdateTimer(props.fpgaDataPort, props.workQueue, 10);
onUpdateWireValues(props.fpgaDataPort);
const subscription = updateTimer.wireOutValuesChangedEvent.subscribe(onUpdateWireValues);
updateTimer.start();
return () => {
updateTimer.stop();
subscription?.cancel();
};
}, [props.fpgaDataPort, onUpdateWireValues]);
Code language: JavaScript (javascript)
The periodic update timer here is set up to call updateWireOuts()
every cycle waiting 10 milliseconds between cycles. Each time that the WireOuts are updated, the timer will notify the FrontPanel component of the event by calling the onUpdateWireValues
event handler that was registered with the subscription.
Once the update timer has been set up with an event handler, it will start the update timer.
Update Event Handler
The update event handler retrieves the current value of the counter and updates the UI state. This occurs every time the update timer signals that there is a new value available.
const onUpdateWireValues = React.useCallback(async (sender?: IFPGADataPortClassic) => {
props.workQueue.post(async () => {
try {
const counterValue = await props.fpgaDataPort.getWireOutValue(0x20) & 0xff;
setCounterValue(counterValue);
}
catch (error) {
console.error(error);
throw new Error(`Failed to update counter value: ${error}`);
}
});
}, [props.fpgaDataPort, props.workQueue]);
Code language: JavaScript (javascript)
Displaying the Counter Value
The FrontPanel component specifies the state variable that will be used to store the current value. The UI components linked to this state variable will display its value every time the UI is redrawn.
const [counterValue, setCounterValue] = React.useState<number>();
Code language: JavaScript (javascript)
The same value is displayed in the text fields one formatted as a decimal value and the other as a hexadecimal value.
return (
<Card>
<Flex direction="column" gap="4">
<Heading size="5" weight="medium">Counter #1</Heading>
<Flex direction="column" align="center" gap="2">
<Box width="80px">
<TextField.Root placeholder="Counter #1 (Decimal)" value={counterValue?.toString()} readOnly>
</TextField.Root>
</Box>
<Box width="80px">
<TextField.Root placeholder="Counter #1 (Hexadecimal)" value={`0x${counterValue?.toString(16)}`} readOnly>
</TextField.Root>
</Box>
</Flex>
<Flex direction="row" align="center" justify="end" gap="2">
<Button size="1" color="red" onMouseDown={onCounterResetButtonDown} onMouseUp={onCounterResetButtonUp}>Reset</Button>
</Flex>
</Flex>
</Card>
);
Code language: JavaScript (javascript)