Included impedance topic.

This commit is contained in:
2025-08-06 15:44:49 +02:00
parent fc27bdc089
commit 3f9f3fedf5
5 changed files with 133 additions and 14 deletions

7
Cargo.lock generated
View File

@@ -74,6 +74,7 @@ dependencies = [
"embassy-time", "embassy-time",
"embassy-usb", "embassy-usb",
"embedded-hal 1.0.0", "embedded-hal 1.0.0",
"libm",
"panic-probe", "panic-probe",
"postcard-rpc", "postcard-rpc",
"static_cell", "static_cell",
@@ -719,6 +720,12 @@ version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "libm"
version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
[[package]] [[package]]
name = "litrs" name = "litrs"
version = "0.4.1" version = "0.4.1"

View File

@@ -22,6 +22,8 @@ bitflags = "2.9.1"
postcard-rpc = {version = "0.11.13", features = ["embassy-usb-0_4-server", "defmt"]} postcard-rpc = {version = "0.11.13", features = ["embassy-usb-0_4-server", "defmt"]}
bioz-icd-rs = {path = "../bioz-icd-rs"} bioz-icd-rs = {path = "../bioz-icd-rs"}
libm = { version = "0.2.15" }
cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] } cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-single-core"] }
cortex-m-rt = "0.7.5" cortex-m-rt = "0.7.5"
# embedded-hal = "0.2.6" # embedded-hal = "0.2.6"

View File

@@ -1,7 +1,10 @@
use defmt::{info, error}; use defmt::info;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex; use embassy_time::{Ticker, Duration};
use embassy_sync::mutex::Mutex;
use embassy_sync::blocking_mutex::raw::{ThreadModeRawMutex, CriticalSectionRawMutex};
use embassy_sync::signal::Signal;
use embassy_stm32::usb::Driver; use embassy_stm32::usb::Driver;
use embassy_stm32::{peripherals, uid, usb}; use embassy_stm32::{peripherals, uid, usb};
@@ -10,19 +13,18 @@ use postcard_rpc::{
header::VarHeader, header::VarHeader,
server::{ server::{
impls::embassy_usb_v0_4::{ impls::embassy_usb_v0_4::{
dispatch_impl::{WireRxBuf, WireRxImpl, WireSpawnImpl, WireStorage, WireTxImpl}, dispatch_impl::{spawn_fn, WireRxBuf, WireRxImpl, WireSpawnImpl, WireStorage, WireTxImpl},
PacketBuffers, PacketBuffers,
}, },
Dispatch, Server, Dispatch, Server, Sender, SpawnContext,
}, },
}; };
use bioz_icd_rs::{PingEndpoint, GetUniqueIdEndpoint, SetGreenLedEndpoint, ENDPOINT_LIST, TOPICS_IN_LIST, TOPICS_OUT_LIST}; use bioz_icd_rs::{PingEndpoint, GetUniqueIdEndpoint, SetGreenLedEndpoint, StartImpedanceEndpoint, StopImpedanceEndpoint, StartImpedance, Impedance, ImpedanceTopic, ENDPOINT_LIST, TOPICS_IN_LIST, TOPICS_OUT_LIST};
pub struct Context { use crate::impedance_test::{ImpedanceTest, IMPEDANCE_TEST};
pub unique_id: [u8; 12],
}
// Postcard RPC types
type AppDriver = usb::Driver<'static, peripherals::USB>; type AppDriver = usb::Driver<'static, peripherals::USB>;
type AppStorage = WireStorage<ThreadModeRawMutex, AppDriver, 256, 256, 64, 256>; type AppStorage = WireStorage<ThreadModeRawMutex, AppDriver, 256, 256, 64, 256>;
type BufStorage = PacketBuffers<1024, 1024>; type BufStorage = PacketBuffers<1024, 1024>;
@@ -34,6 +36,22 @@ use static_cell::ConstStaticCell;
static PBUFS: ConstStaticCell<BufStorage> = ConstStaticCell::new(BufStorage::new()); static PBUFS: ConstStaticCell<BufStorage> = ConstStaticCell::new(BufStorage::new());
static STORAGE: AppStorage = AppStorage::new(); static STORAGE: AppStorage = AppStorage::new();
pub struct Context {
pub unique_id: [u8; 12],
pub impedance: &'static Mutex<ThreadModeRawMutex, ImpedanceTest>,
}
pub struct SpawnCtx {
pub impedance: &'static Mutex<ThreadModeRawMutex, ImpedanceTest>,
}
impl SpawnContext for Context {
type SpawnCtxt = SpawnCtx;
fn spawn_ctxt(&mut self) -> Self::SpawnCtxt {
SpawnCtx { impedance: &self.impedance }
}
}
define_dispatch! { define_dispatch! {
app: MyApp; app: MyApp;
spawn_fn: spawn_fn; spawn_fn: spawn_fn;
@@ -49,6 +67,8 @@ define_dispatch! {
| PingEndpoint | blocking | ping_handler | | PingEndpoint | blocking | ping_handler |
| GetUniqueIdEndpoint | blocking | get_unique_id_handler | | GetUniqueIdEndpoint | blocking | get_unique_id_handler |
| SetGreenLedEndpoint | async | set_green_led_handler | | SetGreenLedEndpoint | async | set_green_led_handler |
| StartImpedanceEndpoint | spawn | start_impedance_handler |
| StopImpedanceEndpoint | async | stop_impedance_handler |
}; };
topics_in: { topics_in: {
list: TOPICS_IN_LIST; list: TOPICS_IN_LIST;
@@ -99,8 +119,10 @@ pub fn init_communication(usb_driver: Driver<'static, peripherals::USB>, spawner
let pbufs = PBUFS.take(); let pbufs = PBUFS.take();
let config = usb_config(); let config = usb_config();
let impedance_ref = IMPEDANCE_TEST.init(embassy_sync::mutex::Mutex::new(ImpedanceTest::new()));
let context = Context { let context = Context {
unique_id: *uid::uid(), unique_id: *uid::uid(),
impedance: impedance_ref,
}; };
let (device, tx_impl, rx_impl) = STORAGE.init(usb_driver, config, pbufs.tx_buf.as_mut_slice()); let (device, tx_impl, rx_impl) = STORAGE.init(usb_driver, config, pbufs.tx_buf.as_mut_slice());
@@ -117,23 +139,75 @@ pub fn init_communication(usb_driver: Driver<'static, peripherals::USB>, spawner
spawner.must_spawn(server_run(server)); spawner.must_spawn(server_run(server));
} }
fn ping_handler(_context: &mut Context, _header: VarHeader, rqst: u32) -> u32 { // Functions
pub fn ping_handler(_context: &mut Context, _header: VarHeader, rqst: u32) -> u32 {
info!("ping"); info!("ping");
rqst rqst
} }
fn get_unique_id_handler(context: &mut Context, _header: VarHeader, _rqst: ()) -> [u8; 12] { pub fn get_unique_id_handler(context: &mut Context, _header: VarHeader, _rqst: ()) -> [u8; 12] {
info!("get_unique_id"); info!("get_unique_id");
context.unique_id context.unique_id
} }
use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex;
use embassy_sync::signal::Signal;
pub static LED_FREQUENCY_SIGNAL: Signal<CriticalSectionRawMutex, f32> = Signal::new(); pub static LED_FREQUENCY_SIGNAL: Signal<CriticalSectionRawMutex, f32> = Signal::new();
async fn set_green_led_handler(_context: &mut Context, _header: VarHeader, rqst: f32) { pub async fn set_green_led_handler(_context: &mut Context, _header: VarHeader, rqst: f32) {
info!("Set green led frequency to {:?} Hz", rqst); info!("Set green led frequency to {:?} Hz", rqst);
LED_FREQUENCY_SIGNAL.signal(rqst); LED_FREQUENCY_SIGNAL.signal(rqst);
}
static STOP: Mutex<ThreadModeRawMutex, bool> = Mutex::new(false);
#[embassy_executor::task]
pub async fn start_impedance_handler(context: SpawnCtx, header: VarHeader, rqst: StartImpedance, sender: Sender<AppTx>) {
info!("Start impedance measurement with interval {:?} ms.", rqst.interval_ms);
let mut impedance = context.impedance.lock().await;
if sender
.reply::<StartImpedanceEndpoint>(header.seq_no, &())
.await
.is_err()
{
defmt::error!("Failed to reply, stopping accel");
return;
}
let mut ticker = Ticker::every(Duration::from_millis(rqst.interval_ms.into()));
let mut seq: u8 = 0;
while !*STOP.lock().await {
ticker.next().await;
impedance.update();
let msg = Impedance {
magnitude: impedance.magnitude,
phase: impedance.phase,
};
if sender
.publish::<ImpedanceTopic>(seq.into(), &msg)
.await
.is_err()
{
defmt::error!("Topic send error!");
break;
}
seq = seq.wrapping_add(1);
}
info!("Impedance measurement stopped.");
*STOP.lock().await = false;
}
pub async fn stop_impedance_handler(context: &mut Context, _header: VarHeader, _rqst: ()) -> bool {
info!("Stop impedance measurement");
let was_busy = context.impedance.try_lock().is_err();
if was_busy {
*STOP.lock().await = true;
}
was_busy
} }

34
src/impedance_test.rs Normal file
View File

@@ -0,0 +1,34 @@
use embassy_sync::mutex::Mutex;
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
use static_cell::StaticCell;
use libm::{sinf, cosf};
use core::f32::consts::PI;
pub static IMPEDANCE_TEST: StaticCell<Mutex<ThreadModeRawMutex, ImpedanceTest>> = StaticCell::new();
pub struct ImpedanceTest {
time: embassy_time::Instant,
pub magnitude: f32,
pub phase: f32,
}
impl ImpedanceTest {
pub fn new() -> Self {
ImpedanceTest {
time: embassy_time::Instant::now(),
magnitude: 1.0,
phase: 0.0,
}
}
pub fn update(&mut self) {
let frequency = 1.0; // Hz, adjust as needed
let current_time = self.time.elapsed().as_millis() as f32 / 1000.0; // Convert to seconds
self.magnitude = cosf(2.0 * PI * frequency * current_time);
self.phase = sinf(2.0 * PI * frequency * current_time);
}
}

View File

@@ -30,6 +30,8 @@ use embassy_stm32::{bind_interrupts, peripherals, usb};
mod communication; mod communication;
use communication::{init_communication, LED_FREQUENCY_SIGNAL}; use communication::{init_communication, LED_FREQUENCY_SIGNAL};
mod impedance_test;
bind_interrupts!(struct Irqs { bind_interrupts!(struct Irqs {
USB_DRD_FS => usb::InterruptHandler<peripherals::USB>; USB_DRD_FS => usb::InterruptHandler<peripherals::USB>;
}); });