### Initialize Raspberry Pi Peripherals with RPPAL Source: https://github.com/golemparts/rppal/blob/master/README.md This example shows how to initialize various Raspberry Pi peripherals using the RPPAL library in Rust. It covers GPIO, I2C, PWM, SPI, and UART, demonstrating the creation of new instances for each peripheral. Ensure necessary configurations are made via `raspi-config` or `config.txt`. ```rust use rppal::gpio::Gpio; use rppal::i2c::I2c; use rppal::pwm::{Channel, Pwm}; use rppal::spi::{Bus, Mode, SlaveSelect, Spi}; use rppal::uart::{Parity, Uart}; let gpio = Gpio::new()?; let i2c = I2c::new()?; let pwm = Pwm::new(Channel::Pwm0)?; let spi = Spi::new(Bus::Spi0, SlaveSelect::Ss0, 16_000_000, Mode::Mode0)?; let uart = Uart::new(115_200, Parity::None, 8, 1)?; ``` -------------------------------- ### Install Rust Target for RPPAL Cross-Compilation Source: https://github.com/golemparts/rppal/blob/master/README.md Installs the necessary Rust target for cross-compilation to Raspberry Pi. This is required for building RPPAL on a different architecture than the target device. The target triple depends on whether the Raspberry Pi OS is 32-bit or 64-bit. ```bash rustup target install armv7-unknown-linux-gnueabihf ``` -------------------------------- ### Get Raspberry Pi System Information (Model, SoC, Peripherals) in Rust Source: https://context7.com/golemparts/rppal/llms.txt This code snippet shows how to retrieve detailed system information about the Raspberry Pi, including its model, SoC type, peripheral base address, and GPIO memory offset using rppal. It provides examples of conditional logic based on the detected Raspberry Pi model. ```rust use rppal::system::DeviceInfo; use std::error::Error; fn main() -> Result<(), Box> { let device_info = DeviceInfo::new()?; // Get model information println!("Model: {}", device_info.model()); println!("SoC: {:?}", device_info.soc()); // Get peripheral base address for direct register access println!("Peripheral base: 0x{:08X}", device_info.peripheral_base()); // Get GPIO memory offset println!("GPIO offset: 0x{:08X}", device_info.gpio_offset()); // Example usage in application match device_info.model() { rppal::system::Model::RaspberryPi5 => { println!("Running on Pi 5 with RP1 I/O controller"); } rppal::system::Model::RaspberryPi4B => { println!("Running on Pi 4 with BCM2711"); } _ => { println!("Running on older Raspberry Pi model"); } } Ok(()) } ``` -------------------------------- ### Handle Signals for Graceful GPIO Cleanup in Rust Source: https://context7.com/golemparts/rppal/llms.txt This example demonstrates how to handle SIGINT and SIGTERM signals to gracefully clean up GPIO state. It uses the `simple_signal` crate to register a handler that sets an atomic boolean flag, allowing the main loop to exit and reset the GPIO pin. Ensure `simple_signal` and `rppal` are added as dependencies. ```rust use rppal::gpio::Gpio; use simple_signal::{self, Signal}; use std::error::Error; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; use std::thread; use std::time::Duration; fn main() -> Result<(), Box> { let gpio = Gpio::new()?; let mut pin = gpio.get(23)?.into_output(); let running = Arc::new(AtomicBool::new(true)); // Handle SIGINT (Ctrl+C) and SIGTERM gracefully simple_signal::set_handler(&[Signal::Int, Signal::Term], { let running = running.clone(); move |_| { running.store(false, Ordering::SeqCst); } }); // Blink LED until signal received while running.load(Ordering::SeqCst) { pin.toggle(); thread::sleep(Duration::from_millis(500)); } // Cleanup: ensure LED is off before exit pin.set_low(); println!("Cleaned up GPIO state"); Ok(()) // Pin resets to original mode on drop (default behavior) } ``` -------------------------------- ### UART - Serial Communication with Rust Source: https://context7.com/golemparts/rppal/llms.txt Configures and utilizes UART for serial data transmission and reception. This example sets up UART with specific baud rate, parity, data bits, and stop bits, then performs a blocking write and read operation. It requires the rppal::uart module and standard library time durations. Useful for basic serial console output or communication with serial devices. ```rust use rppal::uart::{Parity, Uart}; use std::error::Error; use std::time::Duration; fn main() -> Result<(), Box> { // Configure UART: 115200 baud, no parity, 8 data bits, 1 stop bit let mut uart = Uart::new(115_200, Parity::None, 8, 1)?; // Set blocking read mode: wait for at least 1 byte uart.set_read_mode(1, Duration::default())?; // Write data let message = b"Hello, UART!\r\n"; uart.write(message)?; println!("Sent: {:?}", std::str::from_utf8(message).unwrap()); // Read data (blocks until 1+ bytes available) let mut buffer = [0u8; 32]; match uart.read(&mut buffer) { Ok(bytes_read) => { println!("Received {} bytes: {:?}", bytes_read, std::str::from_utf8(&buffer[..bytes_read]).unwrap() ); } Err(e) => println!("Read error: {}", e), } Ok(()) } ``` -------------------------------- ### SPI - Status Polling with Rust Source: https://context7.com/golemparts/rppal/llms.txt Demonstrates how to poll a device's status register using repeated SPI read operations until a specific condition is met, typically to confirm the completion of a write operation. This example shows enabling writes, performing a write, and then polling the status register for the 'Write-In-Process' bit. Requires rppal::spi and Segment. Useful for devices that signal completion asynchronously. ```rust use rppal::spi::{Bus, Mode, Segment, SlaveSelect, Spi}; use std::error::Error; fn main() -> Result<(), Box> { let mut spi = Spi::new(Bus::Spi0, SlaveSelect::Ss0, 8_000_000, Mode::Mode0)?; // Enable write operation const WREN: u8 = 0b0110; spi.write(&[WREN])?; // Write data const WRITE: u8 = 0b0010; spi.write(&[WRITE, 0x00, 0x00, 0x00, 1, 2, 3, 4, 5])?; // Poll status register until write completes const RDSR: u8 = 0b0101; const WIP: u8 = 1; // Write-In-Process bit let mut status = [0u8; 1]; loop { spi.transfer_segments(&[ Segment::with_write(&[RDSR]), Segment::with_read(&mut status), ])?; if status[0] & WIP == 0 { println!("Write complete!"); break; } } Ok(()) } ``` -------------------------------- ### UART - Non-blocking Read with Timeout in Rust Source: https://context7.com/golemparts/rppal/llms.txt Configures UART for non-blocking read operations with a specified timeout. The read function will return immediately if no data is available, or after the timeout duration if no data is received. This example uses a 100ms timeout and prints received data or a 'no data' message. Requires rppal::uart and std::time::Duration. Suitable for applications that need to perform other tasks while waiting for serial data. ```rust use rppal::uart::{Parity, Uart}; use std::error::Error; use std::time::Duration; fn main() -> Result<(), Box> { let mut uart = Uart::new(9600, Parity::Even, 8, 1)?; // Non-blocking mode: return immediately if no data, timeout after 100ms uart.set_read_mode(0, Duration::from_millis(100))?; let mut buffer = [0u8; 128]; loop { match uart.read(&mut buffer) { Ok(0) => { // No data available println!("No data, continuing..."); } Ok(bytes_read) => { println!("Received {} bytes: {:02X?}", bytes_read, &buffer[..bytes_read] ); break; } Err(e) => { println!("Read error: {}", e); break; } } std::thread::sleep(Duration::from_millis(200)); } Ok(()) } ``` -------------------------------- ### Configure VS Code rust-analyzer for RPPAL Target Source: https://github.com/golemparts/rppal/blob/master/README.md Configures the rust-analyzer extension in Visual Studio Code to be aware of the target platform for the RPPAL project. This setting helps rust-analyzer provide accurate code completion, diagnostics, and other language features. Save this snippet to `.vscode/settings.json`. ```json { "rust-analyzer.cargo.target": "armv7-unknown-linux-gnueabihf" } ``` -------------------------------- ### SPI - Basic Transfer with Rust Source: https://context7.com/golemparts/rppal/llms.txt Demonstrates basic full-duplex SPI data transfer, including write-only, read-only, and simultaneous read/write operations. Initializes SPI bus, selects slave device, sets clock speed and mode. Inputs are byte slices for writing and byte slices for reading. Outputs are printed to the console. Requires rppal::spi module. ```rust use rppal::spi::{Bus, Mode, SlaveSelect, Spi}; use std::error::Error; fn main() -> Result<(), Box> { // Initialize SPI: Bus 0, CS0, 8 MHz, Mode 0 let mut spi = Spi::new( Bus::Spi0, SlaveSelect::Ss0, 8_000_000, Mode::Mode0 )?; // Write-only operation spi.write(&[0x01, 0x02, 0x03, 0x04])?; // Read-only operation (sends 0x00 for each byte read) let mut read_buf = [0u8; 4]; spi.read(&mut read_buf)?; println!("Read: {:?}", read_buf); // Full-duplex transfer (simultaneous read/write) let mut buffer = [0x01, 0x02, 0x03, 0x04]; spi.transfer(&mut buffer)?; println!("Transferred: {:?}", buffer); Ok(()) } ``` -------------------------------- ### SPI - Multi-segment Transfer with Rust Source: https://context7.com/golemparts/rppal/llms.txt Illustrates complex SPI transfers involving multiple segments while keeping the Chip Select (CS) line active between segments. Supports writing commands and reading data, or performing writes with custom settings per segment. Requires rppal::spi module and Segment definitions. Useful for EEPROM operations or devices requiring sequential commands. ```rust use rppal::spi::{Bus, Mode, Segment, SlaveSelect, Spi}; use std::error::Error; fn main() -> Result<(), Box> { let mut spi = Spi::new(Bus::Spi0, SlaveSelect::Ss0, 8_000_000, Mode::Mode0)?; // Write command to EEPROM, then read data // CS stays low between segments const READ_CMD: u8 = 0x03; let mut read_buffer = [0u8; 5]; spi.transfer_segments(&[ Segment::with_write(&[READ_CMD, 0x00, 0x00, 0x00]), // Command + address Segment::with_read(&mut read_buffer), // Read data ])?; println!("Data read: {:?}", read_buffer); // Write with custom settings per segment const WRITE_CMD: u8 = 0x02; let write_data = [1, 2, 3, 4, 5]; spi.transfer_segments(&[ Segment::with_write(&[0x06]), // Write enable Segment::with_settings_and_write( 1_000_000, // 1 MHz for write Mode::Mode0, &[WRITE_CMD, 0x00, 0x00, 0x00], ), Segment::with_write(&write_data), ])?; Ok(()) } ``` -------------------------------- ### I2C: Basic Single-Byte Read/Write Operations with Rust Source: https://context7.com/golemparts/rppal/llms.txt Demonstrates fundamental single-byte read and write operations for I2C communication, including a write-then-read sequence. This is useful for simple sensor interactions. Requires `rppal::i2c::I2c`. ```Rust use rppal::i2c::I2c; use std::error::Error; fn main() -> Result<(), Box> { let mut i2c = I2c::new()?; i2c.set_slave_address(0x48)?; // Example: temperature sensor // Write a single byte i2c.write(&[0x01])?; // Read two bytes let mut buffer = [0u8; 2]; i2c.read(&mut buffer)?; // Combine bytes into 16-bit value (big-endian) let value = ((buffer[0] as u16) << 8) | (buffer[1] as u16); println!("Raw value: {}", value); // Write-then-read (common pattern) let mut data = [0u8; 2]; i2c.write_read(&[0x00], &mut data)?; Ok(()) } ``` -------------------------------- ### PWM: Hardware PWM Control with Frequency and Duty Cycle in Rust Source: https://context7.com/golemparts/rppal/llms.txt Configures hardware PWM channels using frequency and duty cycle parameters, suitable for controlling LED brightness or generating audio signals. It allows dynamic changes to frequency and duty cycle. Uses `rppal::pwm::{Channel, Polarity, Pwm}`. ```Rust use rppal::pwm::{Channel, Polarity, Pwm}; use std::error::Error; use std::thread; use std::time::Duration; fn main() -> Result<(), Box> { // Create PWM with frequency and duty cycle let pwm = Pwm::with_frequency( Channel::Pwm1, // GPIO 13, physical pin 33 1000.0, // 1 kHz frequency 0.5, // 50% duty cycle Polarity::Normal, true )?; // LED brightness control example for duty in (0..=100).step_by(5) { pwm.set_duty_cycle(duty as f64 / 100.0)?; thread::sleep(Duration::from_millis(50)); } // Fade out for duty in (0..=100).rev().step_by(5) { pwm.set_duty_cycle(duty as f64 / 100.0)?; thread::sleep(Duration::from_millis(50)); } // Change frequency pwm.set_frequency(2000.0, 0.25)?; // 2 kHz at 25% duty thread::sleep(Duration::from_secs(1)); Ok(()) } ``` -------------------------------- ### Configure Cargo for RPPAL Cross-Compilation Source: https://github.com/golemparts/rppal/blob/master/README.md Configures Cargo to use a specific target for building. This file should be placed in the `.cargo/config.toml` in the root of your project. It ensures that `cargo build` commands respect the specified target architecture. ```toml [build] target = "armv7-unknown-linux-gnueabihf" ``` -------------------------------- ### Add RPPAL Dependency to Cargo.toml Source: https://github.com/golemparts/rppal/blob/master/README.md This snippet demonstrates how to add the RPPAL library as a dependency to your Rust project's Cargo.toml file. It shows the basic dependency declaration and how to enable feature flags for embedded-hal trait implementations. ```toml [dependencies] rppal = "0.22.1" ``` ```toml [dependencies] rppal = { version = "0.22.1", features = ["hal"] } ``` -------------------------------- ### Blink LED with GPIO Source: https://github.com/golemparts/rppal/blob/master/README.md Demonstrates how to blink an LED connected to a GPIO pin using the rppal::gpio module. It requires a resistor in series with the LED to prevent exceeding current limits. The code sets a specific GPIO pin to output mode, turns it high, waits for 500ms, and then turns it low. ```rust use std::error::Error; use std::thread; use std::time::Duration; use rppal::gpio::Gpio; use rppal::system::DeviceInfo; // Gpio uses BCM pin numbering. BCM GPIO 23 is tied to physical pin 16. const GPIO_LED: u8 = 23; fn main() -> Result<(), Box> { println!("Blinking an LED on a {}.", DeviceInfo::new()?.model()); let mut pin = Gpio::new()?.get(GPIO_LED)?.into_output(); // Blink the LED by setting the pin's logic level high for 500 ms. pin.set_high(); thread::sleep(Duration::from_millis(500)); pin.set_low(); Ok(()) } ``` -------------------------------- ### RPPAL GPIO - Input with Pull-up Resistor (Rust) Source: https://context7.com/golemparts/rppal/llms.txt Configures a GPIO pin as an input with an internal pull-up resistor and reads its state. Supports checking `Level::High`/`Level::Low` and `is_high()`/`is_low()` methods. Requires `rppal::gpio`. ```rust use rppal::gpio::{Gpio, Level}; use std::error::Error; fn main() -> Result<(), Box> { let gpio = Gpio::new()?; // Configure pin 17 as input with pull-up resistor let pin = gpio.get(17)?.into_input_pullup(); // Read the pin level if pin.read() == Level::High { println!("Pin is HIGH"); } else { println!("Pin is LOW"); } // Can also use is_high() / is_low() if pin.is_low() { println!("Button pressed (active low)"); } Ok(()) } ``` -------------------------------- ### PWM: Hardware PWM Control with Period and Pulse Width in Rust Source: https://context7.com/golemparts/rppal/llms.txt Controls hardware PWM channels by setting the period and pulse width, ideal for applications like servo control. It allows for precise timing adjustments. Requires `rppal::pwm::{Channel, Polarity, Pwm}`. ```Rust use rppal::pwm::{Channel, Polarity, Pwm}; use std::error::Error; use std::thread; use std::time::Duration; fn main() -> Result<(), Box> { // Initialize PWM channel 0 (GPIO 12, physical pin 32) // 50 Hz (20ms period), 1.8ms pulse width, normal polarity, enabled let pwm = Pwm::with_period( Channel::Pwm0, Duration::from_millis(20), Duration::from_micros(1800), Polarity::Normal, true )?; thread::sleep(Duration::from_millis(500)); // Change pulse width (e.g., for servo control) pwm.set_pulse_width(Duration::from_micros(1200))?; thread::sleep(Duration::from_millis(500)); // Sweep through pulse widths for pulse_us in (1200..=1500).step_by(10) { pwm.set_pulse_width(Duration::from_micros(pulse_us))?; thread::sleep(Duration::from_millis(20)); } // Disable PWM pwm.disable()?; Ok(()) // PWM automatically disabled when dropped } ``` -------------------------------- ### Enable UART Hardware Flow Control (RTS/CTS) in Rust Source: https://context7.com/golemparts/rppal/llms.txt This snippet demonstrates how to enable and disable hardware flow control (RTS/CTS) for UART communication using the rppal library. It includes writing a large data buffer and handling potential write errors. Ensure the UART peripheral is correctly initialized before use. ```rust use rppal::uart::{Parity, Uart}; use std::error::Error; fn main() -> Result<(), Box> { let mut uart = Uart::new(115_200, Parity::None, 8, 1)?; // Enable hardware flow control (RTS/CTS) uart.set_hardware_flow_control(true)?; // Large data transfer with flow control let large_data = vec![0xAA; 1024]; match uart.write(&large_data) { Ok(bytes_written) => { println!("Wrote {} bytes with hardware flow control", bytes_written); } Err(e) => println!("Write error: {}", e), } // Disable flow control uart.set_hardware_flow_control(false)?; Ok(()) } ``` -------------------------------- ### RPPAL GPIO - Software PWM (Rust) Source: https://context7.com/golemparts/rppal/llms.txt Generates a Pulse Width Modulation (PWM) signal on a GPIO pin using software timing. Allows setting the period and pulse width, and stopping the PWM. Requires `rppal::gpio` and `std::time`/`std::thread`. ```rust use rppal::gpio::Gpio; use std::error::Error; use std::thread; use std::time::Duration; fn main() -> Result<(), Box> { let gpio = Gpio::new()?; let mut pin = gpio.get(23)?.into_output(); // Configure software PWM: 50 Hz (20ms period), 1.5ms pulse width // Typical servo control signal pin.set_pwm( Duration::from_millis(20), // Period Duration::from_micros(1500) // Pulse width )?; thread::sleep(Duration::from_millis(500)); // Change pulse width to rotate servo pin.set_pwm( Duration::from_millis(20), Duration::from_micros(1200) )?; thread::sleep(Duration::from_millis(500)); // Stop PWM pin.clear_pwm()?; Ok(()) } ``` -------------------------------- ### RPPAL GPIO - Synchronous Interrupts (Rust) Source: https://context7.com/golemparts/rppal/llms.txt Sets up a synchronous interrupt on a GPIO pin, blocking execution until a trigger event (e.g., FallingEdge) occurs or a timeout is reached. Returns the interrupt level or None on timeout. Requires `rppal::gpio` and `std::time`. ```rust use rppal::gpio::{Gpio, Trigger}; use std::error::Error; use std::time::Duration; fn main() -> Result<(), Box> { let gpio = Gpio::new()?; let pin = gpio.get(17)?.into_input_pullup(); // Configure interrupt for falling edge (button press) pin.set_interrupt(Trigger::FallingEdge)?; println!("Waiting for button press..."); // Block until interrupt occurs or timeout (5 seconds) match pin.poll_interrupt(false, Some(Duration::from_secs(5)))? { Some(level) => println!("Button pressed! Level: {:?}", level), None => println!("Timeout - no interrupt occurred"), } Ok(()) } ``` -------------------------------- ### RPPAL GPIO - Digital Pin Control (Rust) Source: https://context7.com/golemparts/rppal/llms.txt Configures a GPIO pin as an output, sets it high, toggles it, and sets it low. Automatically resets the pin state on drop. Requires `rppal::gpio` and `std::thread`/`std::time`. ```rust use std::error::Error; use std::thread; use std::time::Duration; use rppal::gpio::Gpio; fn main() -> Result<(), Box> { // Initialize GPIO and get pin 23 (BCM numbering) let gpio = Gpio::new()?; let mut pin = gpio.get(23)?.into_output(); // Set pin high for 1 second pin.set_high(); thread::sleep(Duration::from_secs(1)); // Toggle pin state pin.toggle(); thread::sleep(Duration::from_millis(500)); // Set pin low pin.set_low(); Ok(()) // Pin automatically resets to original state when dropped } ``` -------------------------------- ### I2C: SMBus Protocol Operations with Rust Source: https://context7.com/golemparts/rppal/llms.txt Implements SMBus-specific protocols for I2C communication, including read/write byte and word operations, and block write transfers. Suitable for compatible EEPROMs and other devices. Uses `rppal::i2c::I2c`. ```Rust use rppal::i2c::I2c; use std::error::Error; fn main() -> Result<(), Box> { let mut i2c = I2c::new()?; i2c.set_slave_address(0x50)?; // EEPROM example // SMBus write byte: send command + data byte i2c.smbus_write_byte(0x10, 0xAB)?; // SMBus read byte: read from register let value = i2c.smbus_read_byte(0x10)?; println!("Read byte: 0x{:02X}", value); // SMBus write word (16-bit value) i2c.smbus_write_word(0x20, 0x1234)?; // SMBus read word let word = i2c.smbus_read_word(0x20)?; println!("Read word: 0x{:04X}", word); // SMBus block write (up to 32 bytes) i2c.smbus_write_block(0x30, &[1, 2, 3, 4, 5])?; Ok(()) } ``` -------------------------------- ### RPPAL GPIO - Asynchronous Interrupts (Rust) Source: https://context7.com/golemparts/rppal/llms.txt Configures an asynchronous interrupt on a GPIO pin, executing a provided callback function on a separate thread when a trigger event occurs. The main thread continues execution. Requires `rppal::gpio`, `std::thread`, and `std::time`. ```rust use rppal::gpio::{Gpio, Level, Trigger}; use std::error::Error; use std::thread; use std::time::Duration; fn main() -> Result<(), Box> { let gpio = Gpio::new()?; let mut pin = gpio.get(17)?.into_input_pullup(); // Set async interrupt with callback pin.set_async_interrupt(Trigger::FallingEdge, move |level| { println!("Async interrupt triggered! Level: {:?}", level); })?; println!("Async interrupt handler active. Press button..."); // Main thread continues while interrupt handler runs in background thread::sleep(Duration::from_secs(10)); Ok(()) // Interrupt handler automatically cleaned up on drop } ``` -------------------------------- ### I2C: Block Read/Write Operations with Rust Source: https://context7.com/golemparts/rppal/llms.txt Performs block read and write operations on an I2C device, suitable for devices like RTC chips. It includes helper functions for BCD encoding/decoding. Requires the `rppal::i2c::I2c` module. ```Rust use rppal::i2c::I2c; use std::error::Error; use std::thread; use std::time::Duration; // Helper functions for BCD encoding (common in RTC chips) fn bcd2dec(bcd: u8) -> u8 { (((bcd & 0xF0) >> 4) * 10) + (bcd & 0x0F) } fn dec2bcd(dec: u8) -> u8 { ((dec / 10) << 4) | (dec % 10) } fn main() -> Result<(), Box> { let mut i2c = I2c::new()?; // Set slave address (DS3231 RTC at 0x68) i2c.set_slave_address(0x68)?; // Write 3 bytes starting at register 0x00 (seconds, minutes, hours) // Set time to 11:59:50 AM (12-hour format) i2c.block_write( 0x00, &[dec2bcd(50), dec2bcd(59), dec2bcd(11) | (1 << 6)] )?; // Read 3 bytes from register 0x00 let mut buffer = [0u8; 3]; i2c.block_read(0x00, &mut buffer)?; // Display time println!( "{:02}:{:02}:{:02}", bcd2dec(buffer[2] & 0x1F), bcd2dec(buffer[1]), bcd2dec(buffer[0]) ); Ok(()) } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.