103 lines
2.2 KiB
Rust
103 lines
2.2 KiB
Rust
use core::iter::once;
|
|
use embassy_time::{Duration, Timer};
|
|
use esp_hal::gpio::{Flex, Level, Output};
|
|
|
|
async fn spi_delay() {
|
|
Timer::after(Duration::from_micros(1)).await;
|
|
}
|
|
|
|
async fn spi_dummy_bit(sck: &mut Output<'_>) {
|
|
sck.set_low();
|
|
spi_delay().await;
|
|
sck.set_high();
|
|
spi_delay().await;
|
|
}
|
|
|
|
async fn spi_write_bit(bit: bool, mosi: &mut Flex<'_>, sck: &mut Output<'_>) {
|
|
mosi.set_level(if bit { Level::High } else { Level::Low });
|
|
sck.set_low();
|
|
spi_delay().await;
|
|
sck.set_high();
|
|
spi_delay().await;
|
|
}
|
|
|
|
async fn spi_read_bit(mosi: &mut Flex<'_>, sck: &mut Output<'_>) -> bool {
|
|
sck.set_low();
|
|
spi_delay().await;
|
|
sck.set_high();
|
|
spi_delay().await;
|
|
mosi.is_high()
|
|
}
|
|
|
|
async fn spi_write_bits(
|
|
bits: impl Iterator<Item = bool>,
|
|
mosi: &mut Flex<'_>,
|
|
sck: &mut Output<'_>,
|
|
) {
|
|
for bit in bits {
|
|
spi_write_bit(bit, mosi, sck).await;
|
|
}
|
|
}
|
|
|
|
async fn spi_write_word(is_param: bool, data: u8, mosi: &mut Flex<'_>, sck: &mut Output<'_>) {
|
|
assert!(sck.is_set_high());
|
|
spi_write_bits(
|
|
once(is_param).chain((0..8).map(|i| (data >> i) & 1 != 0).rev()),
|
|
mosi,
|
|
sck,
|
|
)
|
|
.await;
|
|
}
|
|
|
|
pub async fn spi_write(
|
|
command: u8,
|
|
args: impl IntoIterator<Item = u8>,
|
|
mosi: &mut Flex<'_>,
|
|
sck: &mut Output<'_>,
|
|
cs: &mut Output<'_>,
|
|
) {
|
|
cs.set_low();
|
|
spi_write_word(false, command, mosi, sck).await;
|
|
|
|
for arg in args {
|
|
spi_write_word(true, arg, mosi, sck).await;
|
|
}
|
|
|
|
cs.set_high();
|
|
}
|
|
|
|
#[expect(unused)]
|
|
pub async fn spi_read(
|
|
command: u8,
|
|
dummy_cycle: bool,
|
|
mosi: &mut Flex<'_>,
|
|
sck: &mut Output<'_>,
|
|
cs: &mut Output<'_>,
|
|
output_buffer: &mut [u8],
|
|
) {
|
|
output_buffer.fill(0);
|
|
|
|
cs.set_low();
|
|
spi_write_word(false, command, mosi, sck).await;
|
|
|
|
mosi.set_output_enable(false);
|
|
mosi.set_input_enable(true);
|
|
|
|
if dummy_cycle {
|
|
spi_dummy_bit(sck).await;
|
|
}
|
|
|
|
for output_byte in output_buffer {
|
|
for i in (0..8).rev() {
|
|
if spi_read_bit(mosi, sck).await {
|
|
*output_byte |= 1 << i;
|
|
}
|
|
}
|
|
}
|
|
|
|
mosi.set_input_enable(false);
|
|
mosi.set_output_enable(true);
|
|
|
|
cs.set_high();
|
|
}
|