Registers & features
Goal of this tutorial:
- Read and write GenApi features such as
ExposureTimeorGain. - Understand how features map to the underlying registers.
- Learn the basics of selectors (e.g.
GainSelector) and how they affect values. - See how to do the same thing from:
- The
gencamctlCLI. - The
genicamRust examples.
- The
If you haven’t done so yet, first go through:
so you know the IP of your camera and which host interface you’re using.
Concepts: features vs registers
GenICam exposes camera configuration through features described in the GenApi XML:
- A feature has a name (
ExposureTime,Gain,PixelFormat, …). - Each feature has a type:
- Integer / Float / Boolean / Enumeration / Command, …
- Under the hood, a feature usually corresponds to one or more registers:
- A simple feature may read/write a single 32-bit register.
- More complex ones may be derived via SwissKnife expressions or depend on selectors.
The genapi-core crate:
- Loads the XML (via
genapi-xml). - Builds a NodeMap.
- Lets you read and write features by name using typed accessors.
The genicam crate and gencamctl CLI sit on top of this NodeMap and try to
hide most of the low-level details.
Step 1 – Inspect features with gencamctl
The gencamctl CLI exposes basic feature access via get and set subcommands. oai_citation:0‡GitHub
You need:
- The camera IP (from the discovery tutorial).
- Optionally, the host interface IP if you have multiple NICs.
1.1. Read a feature by name
Example: read ExposureTime from a camera at 192.168.0.10:
cargo run -p gencamctl -- \
get --ip 192.168.0.10 --name ExposureTime
You should see:
- The current value.
- The type (e.g. Float or Integer).
- Possibly range information (min/max/increment) if available.
If you prefer machine-readable output, add --json:
cargo run -p gencamctl -- \
get --ip 192.168.0.10 --name ExposureTime --json
This is handy for scripting and CI.
1.2. Write a feature by name
To change a value, use the set subcommand. For example, set exposure to 5000 microseconds:
cargo run -p gencamctl -- \
set --ip 192.168.0.10 --name ExposureTime --value 5000
Then verify:
cargo run -p gencamctl -- \
get --ip 192.168.0.10 --name ExposureTime
If the value doesn’t change:
- The feature may be read-only (depending on acquisition state).
- There may be constraints (e.g. limited range, alignment).
- Another feature (like ExposureAuto) may be overriding manual control.
Those cases are described in more depth in the genapi-core chapter.
⸻
Step 2 – Work with selectors
Many cameras use selectors to multiplex multiple logical settings onto the same underlying registers. A common pattern is:
- GainSelector = All, Red, Green, Blue, …
- Gain = value for the currently selected channel.
When you change GainSelector, you are effectively changing which “row” you are editing. The NodeMap takes care of switching the right registers.
2.1. Inspect which selectors exist
You can use gencamctl to dump a selector feature and see its possible values. For example, to inspect GainSelector:
cargo run -p gencamctl -- \
get --ip 192.168.0.10 --name GainSelector --json
Look for:
- The current value (e.g. "All").
- The list of allowed values / enum entries.
2.2. Change a feature through a selector
To set different gains for different channels, a typical sequence is:
# Select the red channel, then set Gain
cargo run -p gencamctl -- \
set --ip 192.168.0.10 --name GainSelector --value Red
cargo run -p gencamctl -- \
set --ip 192.168.0.10 --name Gain --value 5.0
# Select the blue channel, then set Gain
cargo run -p gencamctl -- \
set --ip 192.168.0.10 --name GainSelector --value Blue
cargo run -p gencamctl -- \
set --ip 192.168.0.10 --name Gain --value 3.0
From your perspective, you are just changing features. Internally, genapi-core:
- Evaluates the selector.
- Resolves which nodes and registers are active.
- Applies any SwissKnife expressions as needed.
The selectors_demoexample in the genicam crate shows this pattern in Rust. 
⸻
Step 3 – Do the same from Rust (genicam examples)
The genicam crate provides examples that mirror the CLI operations. 
3.1. Basic get/set example
Run the get_set_feature example:
cargo run -p genicam --example get_set_feature
This example demonstrates:
- Opening a camera (e.g. by IP or by index).
- Getting a feature by name.
- Printing its value and metadata.
- Setting a new value and verifying it.
Inspect the source under crates/genicam/examples/get_set_feature.rs for a minimal template you can reuse in your own project.
Typical pseudo-flow inside that example (simplified):
#![allow(unused)] fn main() { // Pseudocode sketch — see the actual example for details let mut ctx = genicam::Context::new()?; let cam = ctx.open_by_ip("192.168.0.10".parse()?)?; let mut nodemap = cam.nodemap()?; // Read a float feature let exposure: f64 = nodemap.get_float("ExposureTime")?; println!("ExposureTime = {} us", exposure); // Write a new value nodemap.set_float("ExposureTime", 5000.0)?; }
Types and method names may differ slightly; always follow the real example in the repository for exact signatures.
3.2. Selectors demo
To see selector logic in code, run:
cargo run -p genicam --example selectors_demo
This example walks through:
- Enumerating selector values.
- Looping over them to set/read the associated feature.
- Printing out the effective values per selector.
This is a good reference if you need to build a UI that exposes per-channel settings (e.g. separate gains per color channel).
⸻
Step 4 – When you might need raw register access
Most applications should prefer feature-by-name access via GenApi:
- You get type safety (integers vs floats vs enums).
- You respect vendor constraints and SFNC behaviour.
- Your code is more portable across cameras.
However, there are cases where raw registers are still useful:
- Debugging unusual vendor behaviour or firmware bugs.
- Working with undocumented features that are not in the XML.
- Bringing up very early prototypes where the GenApi XML is incomplete.
The lower-level crates (tl-gige and genicp) expose primitives for reading and writing device memory directly. Refer to:
for details and examples. Be careful: writing to arbitrary registers can easily put the device into an unusable state until power-cycled.
⸻
Recap
After this tutorial you should be able to:
- Read and write GenApi features by name using gencamctl.
- Understand and use selector features (e.g. GainSelector → Gain).
- Locate and run the genicam examples (get_set_feature, selectors_demo) as templates for your own applications.
- Know that raw register access exists, but is usually a last resort.
Next step: GenApi XML— how the XML is fetched and turned into the NodeMap that backs these features.