# lvbitfile2rust
[![crates.io](https://img.shields.io/crates/v/lvbitfile2rust.svg)](https://crates.io/crates/lvbitfile2rust)
[![docs.rs](https://docs.rs/lvbitfile2rust/badge.svg)](https://docs.rs/lvbitfile2rust)
[![CI](https://github.com/first-rust-competition/lvbitfile2rust/workflows/CI/badge.svg)](https://github.com/first-rust-competition/lvbitfile2rust/actions?query=workflow%3ACI)
lvbitfile2rust generates static register maps from lvbitx files.
## Invoking from the command line
```sh
cargo install lvbitfile2rust
lvbitfile2rust-cli /boot/user.lvbitx | rustfmt > rio.rs
```
## Invoking as a macro
```rust
mod rio {
use lvbitfile2rust_macros::lvbitfile2rust;
lvbitfile2rust!("/boot/user.lvbitx");
}
```
## Generated code
lvbitfile2rust generates code with a similar interface to code generated by [svd2rust](https://github.com/rust-embedded/svd2rust). The generated code contains a struct named `Peripherals` with an associated function named `take`. Calling `take` will attempt to open an FPGA session and return a `Peripherals` instance. The `Peripherals` instance contains fields for each register described by the input bitfile. These fields contain instances of structs corresponding to each register, with `read` and possibly `write` methods. In practice, the interface is rather straightforward to use:
```rust
use ni_fpga::fxp::UnsignedFXP;
mod rio {
use lvbitfile2rust_macros::lvbitfile2rust;
lvbitfile2rust!("/boot/user.lvbitx");
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
// Turn PWM on if the RSL is on!
// My scope tells me the RSL blinks at 5Hz in teleop mode!
let peripherals = rio::Peripherals::take("RIO0")?;
loop {
let leds = peripherals.LEDs.read()?;
peripherals.PWM_Hdr0.write(&{
if leds.RSL {
UnsignedFXP::max_value()
} else {
UnsignedFXP::min_value()
}
})?;
}
}
```
Generated code will depend on [ni-fpga](https://github.com/first-rust-competition/ni-fpga-rs) and ni-fpga-macros if the input bitfile uses Clusters or Enums.