Skip to content

Commit f26bfa8

Browse files
committed
core: implement core functions
No testing performed as of yet. Only thing missing at this point is polarity. Polarity is not suported in all devices. Signed-off-by: Paul Osborne <osbpau@gmail.com>
1 parent b03064d commit f26bfa8

File tree

1 file changed

+71
-11
lines changed

1 file changed

+71
-11
lines changed

src/lib.rs

Lines changed: 71 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,16 @@ use std::io::prelude::*;
1818
use std::os::unix::prelude::*;
1919
use std::fs::File;
2020
use std::fs;
21+
use std::str::FromStr;
2122
use std::cmp::{min, max};
23+
use std::path::Path;
2224

2325
mod error;
2426
pub use error::Error;
2527

2628
#[derive(Debug)]
2729
pub struct PwmChip {
28-
chip: u32,
30+
pub number: u32,
2931
}
3032

3133
#[derive(Debug)]
@@ -42,14 +44,41 @@ pub enum Polarity {
4244

4345
pub type Result<T> = ::std::result::Result<T, error::Error>;
4446

47+
/// Open the specified entry name as a writable file
48+
fn pwm_file_rw(chip: &PwmChip, pin: u32, name: &str) -> Result<File> {
49+
let f = try!(File::create(format!("/sys/class/pwm/pwmchip{}/pwm{}/{}",
50+
chip.number,
51+
pin,
52+
name)));
53+
Ok(f)
54+
}
55+
56+
/// Open the specified entry name as a readable file
57+
fn pwm_file_ro(chip: &PwmChip, pin: u32, name: &str) -> Result<File> {
58+
let f = try!(File::open(format!("/sys/class/pwm/pwmchip{}/pwm{}/{}", chip.number, pin, name)));
59+
Ok(f)
60+
}
61+
62+
/// Get the u32 value from the given entry
63+
fn pwm_file_parse<T: FromStr>(chip: &PwmChip, pin: u32, name: &str) -> Result<T> {
64+
let mut s = String::with_capacity(10);
65+
let mut f = try!(pwm_file_ro(chip, pin, name));
66+
try!(f.read_to_string(&mut s));
67+
match s.parse::<T>() {
68+
Ok(r) => Ok(r),
69+
Err(_) => Err(Error::Unexpected(format!("Unexpeted value file contents: {:?}", s))),
70+
}
71+
}
72+
73+
4574
impl PwmChip {
46-
pub fn new(chip: u32) -> Result<PwmChip> {
47-
try!(fs::metadata(&format!("/sys/class/pwm/pwmchip{}", chip)));
48-
Ok(PwmChip { chip: chip })
75+
pub fn new(number: u32) -> Result<PwmChip> {
76+
try!(fs::metadata(&format!("/sys/class/pwm/pwmchip{}", number)));
77+
Ok(PwmChip { number: number })
4978
}
5079

5180
pub fn count(&self) -> Result<u32> {
52-
let npwm_path = format!("/sys/class/pwm/pwmchip{}/npwm", self.chip);
81+
let npwm_path = format!("/sys/class/pwm/pwmchip{}/npwm", self.number);
5382
let mut npwm_file = try!(File::open(&npwm_path));
5483
let mut s = String::new();
5584
try!(npwm_file.read_to_string(&mut s));
@@ -62,18 +91,20 @@ impl PwmChip {
6291
pub fn export(&self, number: u32) -> Result<()> {
6392
// only export if not already exported
6493
if let Err(_) = fs::metadata(&format!("/sys/class/pwm/pwmchip{}/pwm{}",
65-
self.chip,
94+
self.number,
6695
number)) {
67-
let path = format!("/sys/class/pwm/pwmchip{}/export", self.chip);
96+
let path = format!("/sys/class/pwm/pwmchip{}/export", self.number);
6897
let mut export_file = try!(File::create(&path));
6998
let _ = export_file.write_all(format!("{}", number).as_bytes());
7099
}
71100
Ok(())
72101
}
73102

74103
pub fn unexport(&self, number: u32) -> Result<()> {
75-
if let Ok(_) = fs::metadata(&format!("/sys/class/pwm/pwmchip{}/pwm{}", self.chip, number)) {
76-
let path = format!("/sys/class/pwm/pwmchip{}/unexport", self.chip);
104+
if let Ok(_) = fs::metadata(&format!("/sys/class/pwm/pwmchip{}/pwm{}",
105+
self.number,
106+
number)) {
107+
let path = format!("/sys/class/pwm/pwmchip{}/unexport", self.number);
77108
let mut export_file = try!(File::create(&path));
78109
let _ = export_file.write_all(format!("{}", number).as_bytes());
79110
}
@@ -116,10 +147,23 @@ impl Pwm {
116147
}
117148

118149
/// Enable/Disable the PWM Signal
119-
pub fn set_active(active: bool) -> Result<()> {
150+
pub fn set_active(&self, active: bool) -> Result<()> {
151+
let mut active_file = try!(pwm_file_rw(&self.chip, self.number, "active"));
152+
let contents = if active {
153+
"1"
154+
} else {
155+
"0"
156+
};
157+
try!(active_file.write_all(contents.as_bytes()));
120158
Ok(())
121159
}
122160

161+
/// Get the currently configured duty cycle as a percentage
162+
pub fn get_duty_cycle(&self) -> Result<f32> {
163+
let raw_duty_cycle = try!(pwm_file_parse::<u32>(&self.chip, self.number, "duty"));
164+
Ok((raw_duty_cycle as f32) / 1000.0)
165+
}
166+
123167
/// Set the duty cycle as a percentage of time active
124168
///
125169
/// This value is expected to be a floating point value
@@ -129,19 +173,35 @@ impl Pwm {
129173
pub fn set_duty_cycle(&self, percent: f32) -> Result<()> {
130174
let raw_percent_adj: u32 = (percent * 1000.0).floor() as u32;
131175
let percent_adj: u32 = max(0, min(raw_percent_adj, 1000));
176+
let mut dc_file = try!(pwm_file_rw(&self.chip, self.number, "duty"));
177+
try!(dc_file.write_all(format!("{}", percent_adj).as_bytes()));
132178
Ok(())
133179
}
134180

181+
/// Get the currently configured duty_cycle in nanoseconds
182+
pub fn get_duty_cycle_ns(&self, duty_cycle_ns: u32) -> Result<u32> {
183+
pwm_file_parse::<u32>(&self.chip, self.number, "duty_cycle")
184+
}
185+
135186
/// The active time of the PWM signal
136187
///
137188
/// Value is in nanoseconds and must be less than the period.
138189
pub fn set_duty_cycle_ns(&self, duty_cycle_ns: u32) -> Result<()> {
139-
190+
// we'll just let the kernel do the validation
191+
let mut duty_cycle_file = try!(pwm_file_rw(&self.chip, self.number, "duty_cycle"));
192+
try!(duty_cycle_file.write_all(format!("{}", duty_cycle_ns).as_bytes()));
140193
Ok(())
141194
}
142195

196+
/// Get the currently configured period in nanoseconds
197+
pub fn get_period_ns(&self) -> Result<u32> {
198+
pwm_file_parse::<u32>(&self.chip, self.number, "period")
199+
}
200+
143201
/// The period of the PWM signal in Nanoseconds
144202
pub fn set_period_ns(&self, period_ns: u32) -> Result<()> {
203+
let mut period_file = try!(pwm_file_rw(&self.chip, self.number, "period"));
204+
try!(period_file.write_all(format!("{}", period_ns).as_bytes()));
145205
Ok(())
146206
}
147207
}

0 commit comments

Comments
 (0)