feat: migrate to parking_lot mutex and add system control architecture
This commit is contained in:
parent
14060e15e5
commit
54144d10e9
29 changed files with 2387 additions and 1130 deletions
|
|
@ -1,6 +1,7 @@
|
|||
use parking_lot::Mutex;
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::sync::Arc;
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
|
|
@ -16,6 +17,8 @@ pub struct GenericClock {
|
|||
high_time: Duration,
|
||||
low_time: Duration,
|
||||
enabled: bool,
|
||||
paused: bool, // Pause state for system control
|
||||
pause_start: Option<Instant>, // When pause started, to track pause duration
|
||||
}
|
||||
|
||||
impl GenericClock {
|
||||
|
|
@ -32,12 +35,27 @@ impl GenericClock {
|
|||
high_time: Duration::from_secs_f64(0.5 / frequency), // Will be recalculated in set_duty_cycle
|
||||
low_time: Duration::from_secs_f64(0.5 / frequency), // Will be recalculated in set_duty_cycle
|
||||
enabled: true,
|
||||
paused: false,
|
||||
pause_start: None,
|
||||
};
|
||||
|
||||
clock.set_duty_cycle(0.5); // Initialize timing
|
||||
clock
|
||||
}
|
||||
|
||||
/// Set the clock frequency dynamically
|
||||
pub fn set_frequency(&mut self, frequency: f64) {
|
||||
if frequency > 0.0 {
|
||||
self.frequency = frequency;
|
||||
self.update_timing();
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the current clock frequency
|
||||
pub fn get_frequency(&self) -> f64 {
|
||||
self.frequency
|
||||
}
|
||||
|
||||
pub fn set_duty_cycle(&mut self, duty_cycle: f64) {
|
||||
self.duty_cycle = duty_cycle.clamp(0.1, 0.9); // Keep within reasonable bounds
|
||||
self.update_timing();
|
||||
|
|
@ -56,6 +74,30 @@ impl GenericClock {
|
|||
self.set_clock_output(PinValue::Low);
|
||||
}
|
||||
|
||||
/// Pause the clock - freeze output state
|
||||
pub fn pause(&mut self) {
|
||||
self.paused = true;
|
||||
self.pause_start = Some(Instant::now());
|
||||
}
|
||||
|
||||
/// Resume the clock from paused state
|
||||
/// Maintains phase consistency by adjusting last_transition to account for pause duration
|
||||
pub fn resume(&mut self) {
|
||||
if let Some(pause_start) = self.pause_start {
|
||||
// Calculate how long we were paused
|
||||
let pause_duration = pause_start.elapsed();
|
||||
// Adjust last_transition forward by the pause duration to maintain phase
|
||||
self.last_transition += pause_duration;
|
||||
}
|
||||
self.paused = false;
|
||||
self.pause_start = None;
|
||||
}
|
||||
|
||||
/// Check if the clock is paused
|
||||
pub fn is_paused(&self) -> bool {
|
||||
self.paused
|
||||
}
|
||||
|
||||
fn frequency_to_duration(frequency: f64) -> Duration {
|
||||
if frequency <= 0.0 {
|
||||
Duration::from_secs(0)
|
||||
|
|
@ -72,17 +114,15 @@ impl GenericClock {
|
|||
|
||||
fn set_clock_output(&self, value: PinValue) {
|
||||
if let Ok(clock_pin) = self.base.get_pin("CLK") {
|
||||
if let Ok(mut pin_guard) = clock_pin.lock() {
|
||||
pin_guard.set_driver(Some(self.base.get_name().to_string()), value);
|
||||
}
|
||||
let mut pin_guard = clock_pin.lock();
|
||||
pin_guard.set_driver(Some(self.base.get_name().to_string()), value);
|
||||
}
|
||||
}
|
||||
|
||||
fn read_enable_pin(&self) -> bool {
|
||||
if let Ok(enable_pin) = self.base.get_pin("ENABLE") {
|
||||
if let Ok(pin_guard) = enable_pin.lock() {
|
||||
return pin_guard.read() == PinValue::High;
|
||||
}
|
||||
let pin_guard = enable_pin.lock();
|
||||
return pin_guard.read() == PinValue::High;
|
||||
}
|
||||
true // Enabled by default if pin doesn't exist or can't be read
|
||||
}
|
||||
|
|
@ -124,6 +164,11 @@ impl Component for GenericClock {
|
|||
}
|
||||
|
||||
fn update(&mut self) {
|
||||
// Check pause state first - don't update if paused
|
||||
if self.paused {
|
||||
return;
|
||||
}
|
||||
|
||||
// Read external enable control
|
||||
let external_enable = self.read_enable_pin();
|
||||
let should_be_enabled = self.enabled && external_enable;
|
||||
|
|
@ -173,9 +218,17 @@ impl Component for GenericClock {
|
|||
self.base.is_running()
|
||||
}
|
||||
|
||||
fn set_running(&mut self, running: bool) {
|
||||
self.base.set_running(running);
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn Any {
|
||||
self
|
||||
}
|
||||
|
||||
fn as_any_mut(&mut self) -> &mut dyn Any {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
// Advanced clock features
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue