mirror of
https://github.com/Djeeberjr/fw-anwesenheit.git
synced 2026-04-30 18:49:09 +00:00
implemented SD card abstraction & used it in IDStore
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
pub mod hardware;
|
||||
pub mod network;
|
||||
pub mod wifi;
|
||||
pub mod sd_card;
|
||||
|
||||
@@ -1,18 +1,18 @@
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_net::Stack;
|
||||
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embedded_sdmmc_dev::SdCard;
|
||||
use esp_hal::i2c::master::Config;
|
||||
use esp_hal::peripherals::{
|
||||
self, GPIO0, GPIO1, GPIO2, GPIO10, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22,
|
||||
GPIO23, I2C0, RMT, SPI2, UART1,
|
||||
GPIO0, GPIO1, GPIO16, GPIO17, GPIO18, GPIO19, GPIO20, GPIO21, GPIO22, GPIO23, I2C0, RMT, SPI2,
|
||||
UART1,
|
||||
};
|
||||
use esp_hal::rmt::{ConstChannelAccess, Rmt, Tx};
|
||||
use esp_hal::rmt::{ConstChannelAccess, Rmt};
|
||||
use esp_hal::spi::{
|
||||
Mode,
|
||||
master::{Config as Spi_config, Spi},
|
||||
};
|
||||
|
||||
use esp_hal::Blocking;
|
||||
use esp_hal::time::Rate;
|
||||
use esp_hal::timer::timg::TimerGroup;
|
||||
use esp_hal::{
|
||||
@@ -23,19 +23,12 @@ use esp_hal::{
|
||||
timer::systimer::SystemTimer,
|
||||
uart::Uart,
|
||||
};
|
||||
|
||||
use esp_hal_smartled::{SmartLedsAdapterAsync, buffer_size_async};
|
||||
|
||||
use smart_leds::colors::{BLUE, GREEN, RED};
|
||||
use smart_leds::{
|
||||
RGB8, SmartLedsWriteAsync, brightness, gamma,
|
||||
hsv::{Hsv, hsv2rgb},
|
||||
};
|
||||
|
||||
use esp_println::logger::init_logger;
|
||||
use log::{debug, error};
|
||||
|
||||
use crate::init::network;
|
||||
use crate::init::sd_card::setup_sdcard;
|
||||
use crate::init::wifi;
|
||||
|
||||
/*************************************************
|
||||
@@ -55,7 +48,7 @@ use crate::init::wifi;
|
||||
*
|
||||
*************************************************/
|
||||
|
||||
pub const NUM_LEDS: usize = 66;
|
||||
pub const NUM_LEDS: usize = 66;
|
||||
pub const LED_BUFFER_SIZE: usize = NUM_LEDS * 25;
|
||||
|
||||
#[panic_handler]
|
||||
@@ -101,15 +94,20 @@ pub async fn hardware_init(
|
||||
|
||||
let i2c_device = setup_i2c(peripherals.I2C0, peripherals.GPIO22, peripherals.GPIO23);
|
||||
|
||||
let spi_device = setup_spi(
|
||||
let spi_bus = setup_spi(
|
||||
peripherals.SPI2,
|
||||
peripherals.GPIO19,
|
||||
peripherals.GPIO20,
|
||||
peripherals.GPIO18,
|
||||
peripherals.GPIO2,
|
||||
);
|
||||
|
||||
let sd_card = setup_sdcard(spi_device);
|
||||
let sd_cs_pin = Output::new(
|
||||
peripherals.GPIO2,
|
||||
esp_hal::gpio::Level::High,
|
||||
OutputConfig::default(),
|
||||
);
|
||||
|
||||
let vol_mgr = setup_sdcard(spi_bus, sd_cs_pin);
|
||||
|
||||
let buzzer_gpio = peripherals.GPIO21;
|
||||
|
||||
@@ -124,8 +122,13 @@ pub async fn hardware_init(
|
||||
|
||||
// Initialize the level shifter for the NFC reader and LED (output-enable (OE) input is low, all outputs are placed in the high-impedance (Hi-Z) state)
|
||||
fn init_lvl_shifter(oe_pin: GPIO0<'static>) {
|
||||
let mut oe_lvl_shifter =
|
||||
Output::new(oe_pin, esp_hal::gpio::Level::Low, OutputConfig::default().with_drive_mode(esp_hal::gpio::DriveMode::PushPull).with_drive_strength(esp_hal::gpio::DriveStrength::_10mA));
|
||||
let mut oe_lvl_shifter = Output::new(
|
||||
oe_pin,
|
||||
esp_hal::gpio::Level::Low,
|
||||
OutputConfig::default()
|
||||
.with_drive_mode(esp_hal::gpio::DriveMode::PushPull)
|
||||
.with_drive_strength(esp_hal::gpio::DriveStrength::_10mA),
|
||||
);
|
||||
oe_lvl_shifter.set_high();
|
||||
}
|
||||
|
||||
@@ -167,24 +170,14 @@ fn setup_spi(
|
||||
sck: GPIO19<'static>,
|
||||
miso: GPIO20<'static>,
|
||||
mosi: GPIO18<'static>,
|
||||
cs: GPIO2<'static>,
|
||||
) -> Spi<'static, Async> {
|
||||
) -> Spi<'static, Blocking> {
|
||||
let spi = match Spi::new(spi2, Spi_config::default()) {
|
||||
Ok(spi) => spi
|
||||
.with_sck(sck)
|
||||
.with_miso(miso)
|
||||
.with_mosi(mosi)
|
||||
.with_cs(cs)
|
||||
.into_async(),
|
||||
Ok(spi) => spi.with_sck(sck).with_miso(miso).with_mosi(mosi),
|
||||
Err(e) => panic!("Failed to initialize SPI: {:?}", e),
|
||||
};
|
||||
spi
|
||||
}
|
||||
|
||||
fn setup_sdcard(spi_device: Spi<'static, Async>) {
|
||||
//let sdcard = SdCard::new(spi_device as embedded_hal::spi::SpiDevice(), delayer)
|
||||
}
|
||||
|
||||
pub fn setup_buzzer(buzzer_gpio: GPIO21<'static>) -> Output<'static> {
|
||||
let config = esp_hal::gpio::OutputConfig::default()
|
||||
.with_drive_strength(esp_hal::gpio::DriveStrength::_40mA);
|
||||
|
||||
84
src/init/sd_card.rs
Normal file
84
src/init/sd_card.rs
Normal file
@@ -0,0 +1,84 @@
|
||||
use alloc::vec::Vec;
|
||||
use embassy_time::Delay;
|
||||
use embedded_hal_bus::spi::ExclusiveDevice;
|
||||
use embedded_sdmmc::{SdCard, TimeSource, Timestamp, VolumeIdx, VolumeManager};
|
||||
use esp_hal::{Blocking, gpio::Output, spi::master::Spi};
|
||||
|
||||
use crate::store::{AttendanceDay, Date, persistence::Persistence};
|
||||
|
||||
pub struct DummyTimesource;
|
||||
|
||||
impl TimeSource for DummyTimesource {
|
||||
fn get_timestamp(&self) -> Timestamp {
|
||||
Timestamp {
|
||||
year_since_1970: 0,
|
||||
zero_indexed_month: 0,
|
||||
zero_indexed_day: 0,
|
||||
hours: 0,
|
||||
minutes: 0,
|
||||
seconds: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type VolMgr = VolumeManager<
|
||||
SdCard<ExclusiveDevice<Spi<'static, Blocking>, Output<'static>, Delay>, Delay>,
|
||||
DummyTimesource,
|
||||
>;
|
||||
|
||||
pub fn setup_sdcard(spi_bus: Spi<'static, Blocking>, cs_pin: Output<'static>) -> SDCardPersistence {
|
||||
let spi_device = ExclusiveDevice::new(spi_bus, cs_pin, Delay).unwrap();
|
||||
let sd_card = SdCard::new(spi_device, Delay);
|
||||
let vol_mgr = VolumeManager::new(sd_card, DummyTimesource);
|
||||
|
||||
SDCardPersistence { vol_mgr }
|
||||
}
|
||||
|
||||
pub struct SDCardPersistence {
|
||||
vol_mgr: VolMgr,
|
||||
}
|
||||
|
||||
impl Persistence for SDCardPersistence {
|
||||
async fn load_day(&mut self, day: crate::store::Date) -> Option<AttendanceDay> {
|
||||
let mut vol_0 = self.vol_mgr.open_volume(VolumeIdx(0)).unwrap();
|
||||
let mut root_dir = vol_0.open_root_dir().unwrap();
|
||||
let mut file = root_dir
|
||||
.open_file_in_dir("days/TODO", embedded_sdmmc::Mode::ReadOnly)
|
||||
.unwrap();
|
||||
|
||||
let mut read_buffer: [u8; 1024] = [0; 1024];
|
||||
let read = file.read(&mut read_buffer).unwrap();
|
||||
file.close().unwrap();
|
||||
|
||||
let day: AttendanceDay = serde_json::from_slice(&read_buffer).unwrap();
|
||||
|
||||
Some(day)
|
||||
}
|
||||
|
||||
async fn save_day(&mut self, day: Date, data: &AttendanceDay) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn load_mapping(&mut self) -> Option<crate::store::IDMapping> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn save_mapping(&mut self, data: &crate::store::IDMapping) {
|
||||
todo!()
|
||||
}
|
||||
|
||||
async fn list_days(&mut self) -> Vec<Date> {
|
||||
let mut vol_0 = self.vol_mgr.open_volume(VolumeIdx(0)).unwrap();
|
||||
let mut root_dir = vol_0.open_root_dir().unwrap();
|
||||
let mut days_dir = root_dir.open_dir("days").unwrap();
|
||||
|
||||
let mut days = Vec::new();
|
||||
days_dir
|
||||
.iterate_dir(|e| {
|
||||
days.push(1);
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
days
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,12 @@
|
||||
use crate::store::persistence::Persistence;
|
||||
|
||||
use super::Date;
|
||||
use super::IDMapping;
|
||||
use super::TallyID;
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::vec::Vec;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Clone)]
|
||||
#[derive(Clone, Deserialize)]
|
||||
pub struct AttendanceDay {
|
||||
date: Date,
|
||||
ids: Vec<TallyID>,
|
||||
@@ -30,42 +32,63 @@ impl AttendanceDay {
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct IDStore {
|
||||
pub days: BTreeMap<Date, AttendanceDay>,
|
||||
pub struct IDStore<T: Persistence> {
|
||||
pub current_day: AttendanceDay,
|
||||
pub mapping: IDMapping,
|
||||
persistence_layer: T,
|
||||
}
|
||||
|
||||
impl IDStore {
|
||||
pub fn new() -> Self {
|
||||
IDStore {
|
||||
days: BTreeMap::new(),
|
||||
mapping: IDMapping::new(),
|
||||
impl<T: Persistence> IDStore<T> {
|
||||
pub async fn new_from_storage(mut persistence_layer: T) -> Self {
|
||||
let mapping = match persistence_layer.load_mapping().await {
|
||||
Some(map) => map,
|
||||
None => IDMapping::new(),
|
||||
};
|
||||
|
||||
let current_date: Date = 1;
|
||||
|
||||
let day = persistence_layer
|
||||
.load_day(current_date)
|
||||
.await
|
||||
.unwrap_or(AttendanceDay::new(current_date));
|
||||
|
||||
Self {
|
||||
current_day: day,
|
||||
mapping,
|
||||
persistence_layer,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_from_storage() -> Self {
|
||||
// TODO: implement
|
||||
todo!()
|
||||
async fn persist_day(&mut self) {
|
||||
self.persistence_layer
|
||||
.save_day(self.current_day.date, &self.current_day)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn persist_mapping(&mut self) {
|
||||
self.persistence_layer.save_mapping(&self.mapping).await
|
||||
}
|
||||
|
||||
/// Add a new id for the current day
|
||||
/// Returns false if ID is already present at the current day.
|
||||
pub fn add_id(&mut self, id: TallyID) -> bool {
|
||||
self.get_current_day().add_id(id)
|
||||
}
|
||||
pub async fn add_id(&mut self, id: TallyID) -> bool {
|
||||
let current_date: Date = 1;
|
||||
|
||||
/// Get the `AttendanceDay` of the current day
|
||||
/// Creates a new if not exists
|
||||
pub fn get_current_day(&mut self) -> &mut AttendanceDay {
|
||||
let current_day: Date = 1;
|
||||
|
||||
if self.days.contains_key(¤t_day) {
|
||||
return self.days.get_mut(¤t_day).unwrap();
|
||||
if self.current_day.date == current_date {
|
||||
let changed = self.current_day.add_id(id);
|
||||
if changed {
|
||||
self.persist_day().await;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
self.days
|
||||
.insert(current_day, AttendanceDay::new(current_day));
|
||||
let new_day = AttendanceDay::new(current_date);
|
||||
self.current_day = new_day;
|
||||
|
||||
self.days.get_mut(¤t_day.clone()).unwrap()
|
||||
let changed = self.current_day.add_id(id);
|
||||
if changed {
|
||||
self.persist_day().await;
|
||||
}
|
||||
changed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
mod id_mapping;
|
||||
pub mod persistence;
|
||||
mod id_store;
|
||||
|
||||
pub use id_mapping::{IDMapping, Name};
|
||||
pub use id_store::IDStore;
|
||||
pub use id_store::{IDStore,AttendanceDay};
|
||||
|
||||
pub type TallyID = [u8; 8];
|
||||
pub type Date = u64;
|
||||
|
||||
12
src/store/persistence.rs
Normal file
12
src/store/persistence.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use crate::store::{Date, IDMapping, id_store::AttendanceDay};
|
||||
|
||||
pub trait Persistence {
|
||||
async fn load_day(&mut self, day: Date) -> Option<AttendanceDay>;
|
||||
async fn save_day(&mut self, day: Date, data: &AttendanceDay);
|
||||
async fn list_days(&mut self) -> Vec<Date>;
|
||||
|
||||
async fn load_mapping(&mut self) -> Option<IDMapping>;
|
||||
async fn save_mapping(&mut self, data: &IDMapping);
|
||||
}
|
||||
Reference in New Issue
Block a user