fix: Beep 有概率崩溃问题。
This commit is contained in:
parent
eb96ce4afb
commit
8bc4be194b
57
src/beep.rs
57
src/beep.rs
@ -4,9 +4,9 @@ use esp_idf_hal::ledc::{config::TimerConfig, Channel, Timer};
|
|||||||
use esp_idf_hal::ledc::{CHANNEL0, TIMER0};
|
use esp_idf_hal::ledc::{CHANNEL0, TIMER0};
|
||||||
use esp_idf_hal::prelude::*;
|
use esp_idf_hal::prelude::*;
|
||||||
use esp_idf_svc::timer::{EspTimer, EspTimerService};
|
use esp_idf_svc::timer::{EspTimer, EspTimerService};
|
||||||
use esp_idf_sys::EspError;
|
use esp_idf_sys::{ledc_mode_t_LEDC_LOW_SPEED_MODE, ledc_set_freq, EspError};
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex, MutexGuard};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
type LedcChannel<P, T, C> = Channel<C, T, Timer<T>, P>;
|
type LedcChannel<P, T, C> = Channel<C, T, Timer<T>, P>;
|
||||||
|
|
||||||
@ -28,16 +28,28 @@ impl BeepState {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BeepChannel = Channel<CHANNEL0, TIMER0, Timer<TIMER0>, Gpio4<Output>>;
|
||||||
|
|
||||||
pub struct Beep {
|
pub struct Beep {
|
||||||
watch_timer: Option<EspTimer>,
|
watch_timer: Option<EspTimer>,
|
||||||
state: BeepState,
|
state: BeepState,
|
||||||
|
channel: Arc<Mutex<BeepChannel>>,
|
||||||
}
|
}
|
||||||
impl Beep {
|
impl Beep {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> anyhow::Result<Self> {
|
||||||
return Beep {
|
let pin = unsafe { Gpio4::<Output>::new() }
|
||||||
|
.into_output()
|
||||||
|
.map_err(|err| anyhow::anyhow!("Failed to set GPIO 4 as ledc output. {}", err))?;
|
||||||
|
let hw_timer = unsafe { TIMER0::new() };
|
||||||
|
let hw_channel = unsafe { CHANNEL0::new() };
|
||||||
|
let mut channel = Self::init_channel(pin, hw_timer, hw_channel, 1000.Hz().into())
|
||||||
|
.map_err(|err| anyhow::anyhow!("Failed to initialize channel. {}", err))?;
|
||||||
|
|
||||||
|
return anyhow::Ok(Beep {
|
||||||
watch_timer: None,
|
watch_timer: None,
|
||||||
state: BeepState::new(),
|
state: BeepState::new(),
|
||||||
};
|
channel: Arc::new(Mutex::new(channel)),
|
||||||
|
});
|
||||||
}
|
}
|
||||||
fn init_channel(
|
fn init_channel(
|
||||||
pin: Gpio4<Output>,
|
pin: Gpio4<Output>,
|
||||||
@ -58,40 +70,37 @@ impl Beep {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let state = Arc::new(Mutex::new(self.state));
|
let state = Arc::new(Mutex::new(self.state));
|
||||||
let mut timer = EspTimerService::new()?.timer(move || {
|
let channel = self.channel.to_owned();
|
||||||
match state.lock().as_mut() {
|
let mut timer = EspTimerService::new()?
|
||||||
|
.timer(move || match state.lock().as_mut() {
|
||||||
Ok(state) => {
|
Ok(state) => {
|
||||||
if let Err(err) = Self::play_once(state) {
|
if let Err(err) = Self::play_once(state, channel.lock().unwrap()) {
|
||||||
warn!("{}", err);
|
warn!("{}", err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!("Failed to lock state. {}", err);
|
warn!("Failed to lock state. {}", err);
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}).map_err(|err| anyhow::anyhow!("Init Timer Failed. {}", err))?;
|
.map_err(|err| anyhow::anyhow!("Init Timer Failed. {}", err))?;
|
||||||
timer.every(Duration::from_millis(250))?;
|
timer.every(Duration::from_millis(250))?;
|
||||||
|
|
||||||
self.watch_timer = Some(timer);
|
self.watch_timer = Some(timer);
|
||||||
return anyhow::Ok(());
|
return anyhow::Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
fn play_once(state: &mut BeepState) -> anyhow::Result<()> {
|
fn play_once(
|
||||||
let pin = unsafe { Gpio4::<Output>::new() }
|
state: &mut BeepState,
|
||||||
.into_output()
|
mut channel: MutexGuard<BeepChannel>,
|
||||||
.map_err(|err| anyhow::anyhow!("Failed to set GPIO 4 as ledc output. {}", err))?;
|
) -> anyhow::Result<()> {
|
||||||
let hw_timer = unsafe { TIMER0::new() };
|
|
||||||
let hw_channel = unsafe { CHANNEL0::new() };
|
|
||||||
if state.ringtone.len() <= state.beat as usize {
|
if state.ringtone.len() <= state.beat as usize {
|
||||||
state.beat = 0;
|
state.beat = 0;
|
||||||
}
|
}
|
||||||
let curr = state.ringtone[state.beat as usize];
|
let curr = state.ringtone[state.beat as usize];
|
||||||
let mut channel = Self::init_channel(pin, hw_timer, hw_channel, if curr < 1000 { 1000.Hz().into()} else {curr.Hz().into()} )
|
if curr == 0 {
|
||||||
.map_err(|err| anyhow::anyhow!("Failed to initialize channel. {}", err))?;
|
|
||||||
|
|
||||||
if curr < 1000 {
|
|
||||||
channel.set_duty(0).expect("Failed to set duty");
|
channel.set_duty(0).expect("Failed to set duty");
|
||||||
} else {
|
} else {
|
||||||
|
unsafe { ledc_set_freq(ledc_mode_t_LEDC_LOW_SPEED_MODE, 0, curr); }
|
||||||
channel.set_duty(60).expect("Failed to set duty");
|
channel.set_duty(60).expect("Failed to set duty");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,7 +114,11 @@ impl Beep {
|
|||||||
pub mod ringtone {
|
pub mod ringtone {
|
||||||
pub type Type = [u32; 16];
|
pub type Type = [u32; 16];
|
||||||
pub const ADAPTER_DOWN: Type = [2300, 2000, 2250, 1950, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
pub const ADAPTER_DOWN: Type = [2300, 2000, 2250, 1950, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
pub const BATTERY_LOW: Type = [2000, 1950, 0, 0, 1980, 1900, 0, 0, 2000, 1900, 0, 0, 1980, 1900, 0, 0];
|
pub const BATTERY_LOW: Type = [
|
||||||
|
2000, 1950, 0, 0, 1980, 1900, 0, 0, 2000, 1900, 0, 0, 1980, 1900, 0, 0,
|
||||||
|
];
|
||||||
pub const SILENCE: Type = [0; 16];
|
pub const SILENCE: Type = [0; 16];
|
||||||
pub const SHUTDOWN: Type = [3450, 3500, 0, 3500, 3050, 3000, 0, 3000, 3050, 1000, 1000, 1000, 0, 0, 0, 0];
|
pub const SHUTDOWN: Type = [
|
||||||
|
3450, 3500, 0, 3500, 3050, 3000, 0, 3000, 3050, 1000, 1000, 1000, 0, 0, 0, 0,
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
@ -44,7 +44,6 @@ fn main() {
|
|||||||
|
|
||||||
let blink_pin = peripherals.pins.gpio5;
|
let blink_pin = peripherals.pins.gpio5;
|
||||||
|
|
||||||
info!("About to start a background event loop");
|
|
||||||
match EspBackgroundEventLoop::new(&Default::default()) {
|
match EspBackgroundEventLoop::new(&Default::default()) {
|
||||||
Ok(eventloop) => unsafe { VOLTAGE_EVENTLOOP = Some(eventloop) },
|
Ok(eventloop) => unsafe { VOLTAGE_EVENTLOOP = Some(eventloop) },
|
||||||
Err(err) => error!("Init Event Loop failed. {:?}", err),
|
Err(err) => error!("Init Event Loop failed. {:?}", err),
|
||||||
@ -72,7 +71,7 @@ fn main() {
|
|||||||
|
|
||||||
sleep(Duration::from_millis(100));
|
sleep(Duration::from_millis(100));
|
||||||
|
|
||||||
let mut beep = Beep::new();
|
let mut beep = Beep::new().unwrap();
|
||||||
|
|
||||||
let mut dc_out_controller =
|
let mut dc_out_controller =
|
||||||
DcOutController::get_instance().expect("Can not get DcOutController instance");
|
DcOutController::get_instance().expect("Can not get DcOutController instance");
|
||||||
|
@ -9,10 +9,7 @@ use std::{
|
|||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use embedded_svc::mqtt::client::{utils::ConnState, Client, Connection, MessageImpl, Publish, QoS};
|
use embedded_svc::mqtt::client::{utils::ConnState, Client, Connection, MessageImpl, Publish, QoS};
|
||||||
use esp_idf_svc::{
|
use esp_idf_svc::mqtt::client::{EspMqttClient, MqttClientConfiguration};
|
||||||
eventloop::{Background, EspEventLoop},
|
|
||||||
mqtt::client::{EspMqttClient, MqttClientConfiguration},
|
|
||||||
};
|
|
||||||
use esp_idf_sys::EspError;
|
use esp_idf_sys::EspError;
|
||||||
use log::*;
|
use log::*;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user