Compare commits

...

2 commits

Author SHA1 Message Date
Frederik Menke 82ef0df464 Move file name generation to own fn 2024-08-10 19:19:51 +02:00
Frederik Menke 8b377a997c Add SdCard spec 2024-08-10 19:19:26 +02:00
2 changed files with 47 additions and 25 deletions

View file

@ -21,14 +21,14 @@ use embassy_rp::spi::Spi;
use embassy_rp::{gpio, spi}; use embassy_rp::{gpio, spi};
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use embassy_sync::channel::Channel; use embassy_sync::channel::Channel;
use embedded_hal_bus::spi::ExclusiveDevice; use embedded_hal_bus::spi::{ExclusiveDevice, NoDelay};
use embedded_sdmmc::sdcard::SdCard; use embedded_sdmmc::sdcard::{self, SdCard};
use embedded_sdmmc::{Block, BlockDevice, BlockIdx, File, VolumeIdx}; use embedded_sdmmc::{Block, BlockDevice, BlockIdx, File, VolumeIdx};
use gpio::{Level, Output}; use gpio::{Level, Output};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
use embassy_rp::i2c::{self, Config}; use embassy_rp::i2c::{self, Config};
use embassy_time::{Duration, Timer}; use embassy_time::{Delay, Duration, Timer};
bind_interrupts!(struct Irqs { bind_interrupts!(struct Irqs {
I2C1_IRQ => i2c::InterruptHandler<embassy_rp::peripherals::I2C1>; I2C1_IRQ => i2c::InterruptHandler<embassy_rp::peripherals::I2C1>;
@ -112,6 +112,7 @@ async fn main(spawner: Spawner) {
loop { loop {
let read_value_if_available = async { let read_value_if_available = async {
let status = co2::get_status(&mut i2c).await?; let status = co2::get_status(&mut i2c).await?;
info!("Sensor status was: {}", status);
// Bit 3 is `DATA_READY` // Bit 3 is `DATA_READY`
if status & 0b00001000u8 != 0 { if status & 0b00001000u8 != 0 {
let measured_value = co2::get_measurement(&mut i2c).await?; let measured_value = co2::get_measurement(&mut i2c).await?;
@ -152,7 +153,7 @@ async fn write_to_sd(spi1: SPI1, pin10: PIN_10, pin11: PIN_11, pin12: PIN_12, pi
let mut config = spi::Config::default(); let mut config = spi::Config::default();
config.frequency = 400_000; config.frequency = 400_000;
let spi = Spi::new_blocking(spi1, pin10, pin11, pin12, config); let spi = Spi::new_blocking(spi1, pin10, pin11, pin12, config);
let cs = Output::new(pin16, Level::High); let cs = Output::new(pin16, Level::Low);
let spi_dev = ExclusiveDevice::new_no_delay(spi, cs); let spi_dev = ExclusiveDevice::new_no_delay(spi, cs);
let sdcard = SdCard::new(spi_dev, embassy_time::Delay); let sdcard = SdCard::new(spi_dev, embassy_time::Delay);
@ -186,35 +187,26 @@ async fn write_to_sd(spi1: SPI1, pin10: PIN_10, pin11: PIN_11, pin12: PIN_12, pi
.unwrap(); .unwrap();
// Open the root directory (mutably borrows from the volume). // Open the root directory (mutably borrows from the volume).
let mut root_dir = volume0.open_root_dir().unwrap();
let mut file_count: usize = 0;
root_dir.iterate_dir(|_| file_count += 1).unwrap();
info!("Found {} files", file_count);
// ShortFileName::FILENAME_MAX_LEN == 11. Therefore, we can't go any longer
// However, this should be fine as we have 8 chars => 10^8 = 100000000
// possible files.
let mut file_name_buffer = [0; 11];
let mut cursor = Cursor::new(&mut file_name_buffer[..]);
core::write!(&mut cursor, "{}.txt", file_count + 1)
.expect("File count + extension should definetly fit into 11 bytes");
let final_position = cursor.position() as usize;
let file_name = core::str::from_utf8(&file_name_buffer[..final_position])
.expect("We only put ASCII into the buffer");
let (len, file_name_buffer) = generate_file_name(&mut volume0);
let file_name = Some(
core::str::from_utf8(&file_name_buffer[..len]).expect("We only put ASCII into the buffer"),
);
info!("Creating new text file: {}", file_name); info!("Creating new text file: {}", file_name);
let mut root_dir = volume0.open_root_dir().unwrap();
let mut file = root_dir let mut file = root_dir
.open_file_in_dir(file_name, embedded_sdmmc::Mode::ReadWriteCreateOrAppend) .open_file_in_dir(
file_name.unwrap(),
embedded_sdmmc::Mode::ReadWriteCreateOrAppend,
)
.unwrap(); .unwrap();
loop { loop {
let new_value = MEASUREMENT_VALUES.receive().await; let new_value = MEASUREMENT_VALUES.receive().await;
info!( info!(
"Writing measurement value {} to file {}.TXT", "Writing measurement value {} to file {}",
new_value, new_value, file_name
file_count + 1
); );
// Space for five characters to fit numbers up to 65535 + '\n' // Space for five characters to fit numbers up to 65535 + '\n'
@ -230,13 +222,43 @@ async fn write_to_sd(spi1: SPI1, pin10: PIN_10, pin11: PIN_11, pin12: PIN_12, pi
}; };
if let Err(e) = write_flush() { if let Err(e) = write_flush() {
error!( error!(
"Failed to write measuement: {:?}.\nIgnoring missing value...", "Failed to write measuement: {:?}.\nTrying to reinitialize card...",
defmt::Debug2Format(&e) defmt::Debug2Format(&e)
); );
sdcard.mark_card_uninit();
} }
} }
} }
type SdCardConcrete<'a, 'b> = SdCard<
ExclusiveDevice<Spi<'a, SPI1, embassy_rp::spi::Blocking>, Output<'b, PIN_16>, NoDelay>,
Delay,
>;
/// Generate a file name for the new data file.
///
/// The generated name is just going to be "<number-of-files-in-volume>.TXT"
pub fn generate_file_name(
volume: &mut embedded_sdmmc::Volume<'_, SdCardConcrete, DummyTimesource, 4, 4, 1>,
) -> (usize, [u8; 11]) {
// Open the root directory (mutably borrows from the volume).
let mut root_dir = volume.open_root_dir().unwrap();
let mut file_count: usize = 0;
root_dir.iterate_dir(|_| file_count += 1).unwrap();
info!("Found {} files", file_count);
// ShortFileName::FILENAME_MAX_LEN == 11. Therefore, we can't go any longer
// However, this should be fine as we have 8 chars => 10^8 = 100000000
// possible files.
let mut file_name_buffer = [0; 11];
let mut cursor = Cursor::new(&mut file_name_buffer[..]);
core::write!(&mut cursor, "{}.txt", file_count + 1)
.expect("File count + extension should definetly fit into 11 bytes");
let final_position = cursor.position() as usize;
(final_position, file_name_buffer)
}
pub fn valid_volumes<D>(block_device: &mut D) -> [Option<(VolumeIdx, [u8; 11])>; 4] pub fn valid_volumes<D>(block_device: &mut D) -> [Option<(VolumeIdx, [u8; 11])>; 4]
where where
D: BlockDevice, D: BlockDevice,