Learn how to communicate with SPI devices using the PoKeys SPI master interface
use pokeys_lib::*;
use std::thread;
use std::time::Duration;
fn main() -> Result<()> {
// Connect to device
let device_count = enumerate_usb_devices()?;
if device_count == 0 {
println!("No PoKeys devices found");
return Ok(());
}
let mut device = connect_to_device(0)?;
println!("Connected to PoKeys device");
// Configure SPI with 1MHz clock
let spi_config = SpiConfiguration {
clock_frequency: 1_000_000, // 1 MHz
mode: SpiMode::Mode0, // CPOL=0, CPHA=0
bit_order: SpiBitOrder::MsbFirst,
};
device.configure_spi(spi_config)?;
println!("SPI configured: 1MHz, Mode 0, MSB first");
// Configure chip select pin
let cs_pin = 10;
device.set_pin_function(cs_pin, PinFunction::DigitalOutput)?;
device.set_digital_output(cs_pin, true)?; // CS idle high
// Example: Read device ID from SPI sensor
let device_id = read_spi_device_id(&mut device, cs_pin)?;
println!("SPI Device ID: 0x{:02X}", device_id);
Ok(())
}
fn read_spi_device_id(device: &mut PoKeysDevice, cs_pin: u8) -> Result<u8> {
// Pull CS low to start transaction
device.set_digital_output(cs_pin, false)?;
thread::sleep(Duration::from_micros(10));
// Send read ID command (example: 0x9F for many flash chips)
let tx_data = vec![0x9F, 0x00]; // Command + dummy byte
let rx_data = device.spi_transfer(&tx_data)?;
// Pull CS high to end transaction
device.set_digital_output(cs_pin, true)?;
// Return device ID (second byte in response)
Ok(rx_data[1])
} use pokeys_lib::*;
use std::collections::HashMap;
struct SpiDevice {
cs_pin: u8,
name: String,
}
fn main() -> Result<()> {
let mut device = connect_to_device(0)?;
// Configure SPI bus
let spi_config = SpiConfiguration {
clock_frequency: 2_000_000, // 2 MHz
mode: SpiMode::Mode0,
bit_order: SpiBitOrder::MsbFirst,
};
device.configure_spi(spi_config)?;
// Define multiple SPI devices
let mut spi_devices = HashMap::new();
spi_devices.insert("flash", SpiDevice { cs_pin: 10, name: "Flash Memory".to_string() });
spi_devices.insert("adc", SpiDevice { cs_pin: 11, name: "ADC Converter".to_string() });
spi_devices.insert("dac", SpiDevice { cs_pin: 12, name: "DAC Output".to_string() });
// Configure all CS pins
for spi_dev in spi_devices.values() {
device.set_pin_function(spi_dev.cs_pin, PinFunction::DigitalOutput)?;
device.set_digital_output(spi_dev.cs_pin, true)?; // CS idle high
println!("Configured CS pin {} for {}", spi_dev.cs_pin, spi_dev.name);
}
// Communicate with each device
for (key, spi_dev) in &spi_devices {
match key {
"flash" => {
let id = read_flash_id(&mut device, spi_dev.cs_pin)?;
println!("Flash ID: 0x{:04X}", id);
},
"adc" => {
let value = read_adc_channel(&mut device, spi_dev.cs_pin, 0)?;
println!("ADC Channel 0: {}", value);
},
"dac" => {
write_dac_value(&mut device, spi_dev.cs_pin, 2048)?;
println!("DAC set to mid-scale");
},
_ => {}
}
}
Ok(())
}
fn read_flash_id(device: &mut PoKeysDevice, cs_pin: u8) -> Result<u16> {
device.set_digital_output(cs_pin, false)?;
let tx_data = vec![0x90, 0x00, 0x00, 0x00, 0x00]; // Read ID command
let rx_data = device.spi_transfer(&tx_data)?;
device.set_digital_output(cs_pin, true)?;
Ok(((rx_data[3] as u16) << 8) | (rx_data[4] as u16))
}
fn read_adc_channel(device: &mut PoKeysDevice, cs_pin: u8, channel: u8) -> Result<u16> {
device.set_digital_output(cs_pin, false)?;
let tx_data = vec![0x01, (channel << 4) | 0x80, 0x00]; // Start bit + channel
let rx_data = device.spi_transfer(&tx_data)?;
device.set_digital_output(cs_pin, true)?;
Ok(((rx_data[1] as u16 & 0x0F) << 8) | (rx_data[2] as u16))
}
fn write_dac_value(device: &mut PoKeysDevice, cs_pin: u8, value: u16) -> Result<()> {
device.set_digital_output(cs_pin, false)?;
let tx_data = vec![
0x30 | ((value >> 8) & 0x0F) as u8, // Command + upper 4 bits
(value & 0xFF) as u8, // Lower 8 bits
];
device.spi_transfer(&tx_data)?;
device.set_digital_output(cs_pin, true)?;
Ok(())
} Clock idle low, data sampled on rising edge
Clock idle low, data sampled on falling edge
Clock idle high, data sampled on falling edge
Clock idle high, data sampled on rising edge
// Configure different SPI modes
let configs = [
SpiConfiguration { mode: SpiMode::Mode0, clock_frequency: 1_000_000, bit_order: SpiBitOrder::MsbFirst },
SpiConfiguration { mode: SpiMode::Mode1, clock_frequency: 500_000, bit_order: SpiBitOrder::LsbFirst },
SpiConfiguration { mode: SpiMode::Mode2, clock_frequency: 2_000_000, bit_order: SpiBitOrder::MsbFirst },
SpiConfiguration { mode: SpiMode::Mode3, clock_frequency: 100_000, bit_order: SpiBitOrder::MsbFirst },
];
// Apply configuration based on device requirements
device.configure_spi(configs[0])?; // Most common: Mode 0