RemoteCommand
RemoteCommand is the right choice when a tree action is
really a hardware-backed write, but should read like a command rather than like
persistent state. It combines Command invocation behavior with
RemoteVariable register mapping.
Typical use cases include:
Triggering a hardware reset register
Pulsing a self-clearing strobe bit
Touching a command register with a fixed value
Issuing a posted write when the command bit should not be read back
When To Use RemoteCommand
Use RemoteCommand when the tree should expose “do this now”, but the
implementation still lives in a memory-mapped field.
This is often a better fit than a writable RemoteVariable for reset pulses,
update strobes, trigger bits, apply bits, and other actions that are not meant
to represent persistent operator-managed state.
What You Usually Set
Most RemoteCommand definitions use the shared command behavior from
Command together with the remote mapping parameters
that describe the hardware field:
offsetfor the register addressbitSizeandbitOffsetfor the command fieldbasefor the underlying data modelfunctionfor the command action policyvaluewhen the command has a meaningful default argument
In practice, function is the parameter that most strongly determines what
invoking the command actually does.
How RemoteCommand Works
RemoteCommand is still a Command node, so users invoke it as
cmd() or cmd(arg). Under the hood, the command callback receives the
normal command wrapper keywords:
rootdevcmdarg
For RemoteCommand, the callback usually operates by calling methods on
cmd such as:
cmd.set(value)cmd.get(read=True)cmd.post(value)
That is why the built-in helper functions work so well here: they are small command policies layered on top of the mapped register field.
Built-In Command Functions
PyRogue includes several built-in helper functions on
BaseCommand that are commonly passed as the function
for a RemoteCommand.
In code, these are often referenced as either pr.BaseCommand.touchOne or
pr.RemoteCommand.touchOne because RemoteCommand inherits from
BaseCommand.
The most important ones are:
togglewrites1and then0touchOnewrites1touchZerowrites0touchwrites the supplied argument, or1when no argument is givenpostedTouchOneposts1without the normal blocking write pathpostedTouchZeroposts0without the normal blocking write pathpostedTouchposts the supplied argumentcreateTouch(value)creates a helper that always writes one fixed valuecreatePostedTouch(value)creates a posted helper for one fixed valuecreateToggle(values)creates a helper that writes a configured sequence of valuessetArgwrites the supplied argumentsetAndVerifyArgwrites the supplied argument and checks that it reads back correctlyreadperforms a read of the mapped command field
The right helper depends on the hardware semantics.
toggle For Pulse-Style Commands
Use toggle when the action is represented by a 1 -> 0 pulse.
import pyrogue as pr
class MyDevice(pr.Device):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add(pr.RemoteCommand(
name='CountReset',
description='Pulse the hardware counter reset bit',
offset=0x00,
bitSize=1,
bitOffset=0,
base=pr.UInt,
function=pr.BaseCommand.toggle,
))
This is one of the most common RemoteCommand patterns in real hardware
trees.
touchOne And touchZero For Fixed-Value Writes
Use these when the hardware action is a single fixed write rather than a pulse sequence.
import pyrogue as pr
class MyDevice(pr.Device):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add(pr.RemoteCommand(
name='DeviceUpdate',
description='Latch recently written configuration values',
offset=0x3FC,
bitSize=1,
base=pr.UInt,
function=pr.BaseCommand.touchZero,
))
touchOne is similarly common for self-clearing strobe bits that trigger on
the write of 1.
touch For Argument-Driven Writes
Use touch when the command should write the caller-provided argument.
import pyrogue as pr
class MyDevice(pr.Device):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add(pr.RemoteCommand(
name='FreezeDebug',
description='Write the debug freeze control field',
offset=0xA0,
bitSize=1,
base=pr.UInt,
value=1,
function=pr.BaseCommand.touch,
))
Calling FreezeDebug(1) writes 1. Calling FreezeDebug(0) writes
0. If the caller omits the argument, touch falls back to 1.
postedTouch... For Posted Writes
Use the posted variants when the hardware command should be issued through
post() rather than the normal blocking write path.
import pyrogue as pr
class MyDevice(pr.Device):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add(pr.RemoteCommand(
name='FpgaReload',
description='Request FPGA reload through a posted write',
offset=0x104,
bitSize=1,
bitOffset=0,
base=pr.UInt,
function=pr.BaseCommand.postedTouchOne,
))
This pattern is useful when the command bit is self-clearing, has unusual readback behavior, or should not participate in the normal write/verify path.
createTouch And createToggle For Captured Policies
The create... helpers are factories that return command functions with a
captured fixed value or sequence. They are useful when the hardware protocol
does not match one of the standard one-line helpers directly.
import pyrogue as pr
class MyDevice(pr.Device):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add(pr.RemoteCommand(
name='SpecialKick',
description='Write the required three-step kick sequence',
offset=0x20,
bitSize=8,
base=pr.UInt,
function=pr.BaseCommand.createToggle([0x5A, 0xA5, 0x00]),
))
Likewise, createTouch(0x81) is a compact way to define a command that
always writes 0x81. createPostedTouch(0x81) does the same thing
through post() instead of set().
setArg And setAndVerifyArg For Argument-Carrying Commands
These helpers are useful when the command node should behave like an explicit command wrapper around a writable field.
import pyrogue as pr
class MyDevice(pr.Device):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add(pr.RemoteCommand(
name='StartAddress',
description='Write the capture start address through a command node',
offset=0x40,
bitSize=32,
base=pr.UInt,
value=0,
function=pr.BaseCommand.setAndVerifyArg,
))
This is less common than the strobe-style helpers, but it can be useful when you want the tree surface to read like an action rather than like persistent register state.
The read helper is also available, though it is more specialized. It is
mainly useful for diagnostic or synchronization cases where invoking the
command should explicitly perform a read of the mapped command field.
Custom Command Functions
You are not limited to the built-in helpers. A custom callback is appropriate when the hardware action needs a small amount of extra policy.
import pyrogue as pr
class MyDevice(pr.Device):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.add(pr.RemoteCommand(
name='ReloadAtAddress',
description='Write a reload request using the current address field',
offset=0x104,
bitSize=1,
base=pr.UInt,
function=lambda cmd: cmd.post(1),
))
Use a custom function when the command behavior is still simple but does not fit one of the built-in helpers cleanly.
What To Explore Next
Software-defined commands: LocalCommand
Shared command behavior: Command
Hardware-backed Variables: RemoteVariable
API Reference
See RemoteCommand for generated API details.