add lifeline

This commit is contained in:
Aiden McClelland
2020-12-24 14:33:38 -07:00
parent 69cfe3daf4
commit e8a693049e
7 changed files with 135 additions and 0 deletions

2
lifeline/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
/target
**/*.rs.bk

6
lifeline/Cargo.lock generated Normal file
View File

@@ -0,0 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "lifeline"
version = "0.1.0"

9
lifeline/Cargo.toml Normal file
View File

@@ -0,0 +1,9 @@
[package]
name = "lifeline"
version = "0.1.0"
authors = ["Keagan McClelland <keagan.mcclelland@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

10
lifeline/lifeline.service Normal file
View File

@@ -0,0 +1,10 @@
[Unit]
Description=Boot process for system reset.
[Service]
Type=oneshot
ExecStart=/usr/local/bin/lifeline
RemainAfterExit=true
[Install]
WantedBy=multi-user.target

1
lifeline/rustfmt.toml Normal file
View File

@@ -0,0 +1 @@
max_width = 120

14
lifeline/src/main.rs Normal file
View File

@@ -0,0 +1,14 @@
use std::time::Duration;
mod sound;
use sound::{notes::*, Song};
const SUCCESS_SONG: Song = Song(&[(Some(A_4), Duration::from_millis(100))]);
fn main() {
std::fs::write("/sys/class/pwm/pwmchip0/export", "0").unwrap();
let res = SUCCESS_SONG.play();
std::fs::write("/sys/class/pwm/pwmchip0/unexport", "0").unwrap();
res.unwrap();
}

93
lifeline/src/sound.rs Normal file
View File

@@ -0,0 +1,93 @@
#![allow(dead_code)]
use std::io::Error;
use std::time::Duration;
pub mod notes {
pub const A_4: f64 = 440.0;
pub const B_4: f64 = 493.88;
pub const C_5: f64 = 523.25;
pub const D_5: f64 = 587.33;
pub const E_5: f64 = 659.25;
pub const F_5: f64 = 698.46;
pub const G_5: f64 = 783.99;
pub const A_5: f64 = 880.00;
pub const B_5: f64 = 987.77;
pub const E_6: f64 = 1318.51;
}
pub fn freq_to_period(freq: f64) -> Duration {
Duration::from_secs(1).div_f64(freq)
}
pub fn play(freq: f64) -> Result<(), Error> {
// set freq
let period = freq_to_period(freq);
let period_bytes = std::fs::read("/sys/class/pwm/pwmchip0/pwm0/period")?;
if period_bytes == b"0\n" {
std::fs::write("/sys/class/pwm/pwmchip0/pwm0/period", format!("{}", 1000))?;
}
std::fs::write("/sys/class/pwm/pwmchip0/pwm0/duty_cycle", "0")?;
std::fs::write("/sys/class/pwm/pwmchip0/pwm0/period", format!("{}", period.as_nanos()))?;
std::fs::write(
"/sys/class/pwm/pwmchip0/pwm0/duty_cycle",
format!("{}", (period / 2).as_nanos()),
)?;
// enable the thing
std::fs::write("/sys/class/pwm/pwmchip0/pwm0/enable", "1")?;
Ok(())
}
pub fn stop() -> Result<(), Error> {
// disable the thing
std::fs::write("/sys/class/pwm/pwmchip0/pwm0/enable", "0")?;
// sleep small amount
std::thread::sleep(Duration::from_micros(30));
Ok(())
}
pub fn play_for_duration(freq: f64, duration: Duration) -> Result<(), Error> {
play(freq)?;
std::thread::sleep(duration);
stop()
}
#[derive(Clone, Debug)]
pub struct Song<'a>(pub &'a [(Option<f64>, Duration)]);
impl<'a> Song<'a> {
pub fn play(&self) -> Result<(), Error> {
for (note, duration) in self.0 {
if let Some(note) = note {
play_for_duration(*note, *duration)?;
} else {
std::thread::sleep(*duration);
}
}
Ok(())
}
}
impl Song<'static> {
pub fn play_while<T, F: FnOnce() -> T>(&'static self, f: F) -> T {
let run = std::sync::Arc::new(std::sync::atomic::AtomicBool::new(true));
let t_run = run.clone();
let handle = std::thread::spawn(move || -> Result<(), Error> {
while t_run.load(std::sync::atomic::Ordering::SeqCst) {
self.play()?;
}
Ok(())
});
let res = f();
run.store(false, std::sync::atomic::Ordering::SeqCst);
let e = handle.join().unwrap().err();
if let Some(e) = e {
eprintln!("ERROR PLAYING SOUND: {}\n{:?}", e, e);
}
res
}
}
impl<'a> From<&'a [(Option<f64>, Duration)]> for Song<'a> {
fn from(t: &'a [(Option<f64>, Duration)]) -> Self {
Song(t)
}
}