Rust beginner here! I'm working on a shift register driver, and I need some help with modifying the split method to return ([Parts;N], ShiftRegister<SPI, N>).
Specifically, I want each instance in the array of Parts to have its byte field increment from 0 to N.
Can a macro be used to generate these Parts items automatically?
Here's the code snippet I'm working with:
use std::sync::Arc;
use std::sync::Mutex;
use embedded_hal as hal;
use hal::blocking::spi::Write;
pub enum DriverError {
UpdateFailure,
}
pub struct IC74hc594<SPI, const N: usize> {
spi: SPI,
state: Arc<Mutex<[u8; N]>>,
}
impl<SPI, const N: usize> IC74hc594<SPI, N>
where
SPI: Write<u8>,
{
pub fn new(spi: SPI) -> Self {
Self {
spi: spi,
state: Arc::new(Mutex::new([0; N])),
}
}
pub fn split(self) -> (Parts<N>, ShiftRegister<SPI, N>) {
(
Parts {
Q0: RegisterPin {
state: Arc::clone(&self.state),
byte: 0,
bit: 0,
},
Q1: RegisterPin {
state: Arc::clone(&self.state),
byte: 0,
bit: 1,
},
Q2: RegisterPin {
state: Arc::clone(&self.state),
byte: 0,
bit: 2,
},
Q3: RegisterPin {
state: Arc::clone(&self.state),
byte: 0,
bit: 3,
},
Q4: RegisterPin {
state: Arc::clone(&self.state),
byte: 0,
bit: 4,
},
Q5: RegisterPin {
state: Arc::clone(&self.state),
byte: 0,
bit: 5,
},
Q6: RegisterPin {
state: Arc::clone(&self.state),
byte: 0,
bit: 6,
},
Q7: RegisterPin {
state: Arc::clone(&self.state),
byte: 0,
bit: 7,
},
},
ShiftRegister {
spi: self.spi,
state: self.state,
},
)
}
}
#[allow(non_snake_case)]
pub struct Parts<const N: usize> {
Q0: RegisterPin<N>,
Q1: RegisterPin<N>,
Q2: RegisterPin<N>,
Q3: RegisterPin<N>,
Q4: RegisterPin<N>,
Q5: RegisterPin<N>,
Q6: RegisterPin<N>,
Q7: RegisterPin<N>,
}
pub struct ShiftRegister<SPI, const N: usize> {
spi: SPI,
state: Arc<Mutex<[u8; N]>>,
}
impl<SPI, const N: usize> ShiftRegister<SPI, N>
where
SPI: Write<u8>,
{
pub fn update(&mut self) -> Result<(), DriverError> {
let state = Arc::clone(&self.state);
let mut state = state.lock().unwrap();
self.spi
.write(state.as_mut())
.or(Err(DriverError::UpdateFailure))
}
}
pub struct RegisterPin<const N: usize> {
state: Arc<Mutex<[u8; N]>>,
byte: usize,
bit: usize,
}
impl<const N: usize> RegisterPin<N> {
pub fn set(&self) {
let mut state = self.state.lock().unwrap();
state[self.byte / 8] |= 1 << self.bit;
}
pub fn clear(&self) {
let mut state = self.state.lock().unwrap();
state[self.byte / 8] &= !(1 << self.bit);
}
}