Skip to content

Commit d461a47

Browse files
committed
core: initial paritial implementation (WIP)
The error code is mostly borrowed from sysfs-gpio and the following functions are implemented for Pwm: * new * export * unexported * with_exported Signed-off-by: Paul Osborne <osbpau@gmail.com>
1 parent ae4018b commit d461a47

File tree

3 files changed

+165
-6
lines changed

3 files changed

+165
-6
lines changed

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ Controlling a PWM (this example works on the Rasbperry Pi):
3535

3636
```rust
3737
extern crate sysfs_pwm;
38-
use sysfs_pwm::{PWM};
38+
use sysfs_pwm::{Pwm};
3939

4040
const RPI_PWM_CHIP: u32 = 1;
4141

42-
fn pwm_increase_to_max(pwm: &PWM,
42+
fn pwm_increase_to_max(pwm: &Pwm,
4343
duration_ms: u32,
4444
update_period: u32) {
4545
let mut step: f32 = duration_ms / update_period;
@@ -51,7 +51,7 @@ fn pwm_increase_to_max(pwm: &PWM,
5151
pwm.set_duty_cycle(1.0);
5252
}
5353

54-
fn pwm_decrease_to_minimum(pwm: &PWM,
54+
fn pwm_decrease_to_minimum(pwm: &Pwm,
5555
duration_ms: u32,
5656
update_period: u32) {
5757
let mut step: f32 = duration_ms / update_period;
@@ -66,7 +66,7 @@ fn pwm_decrease_to_minimum(pwm: &PWM,
6666
/// Make an LED "breathe" by increasing and
6767
/// decreasing the brightness
6868
fn main() {
69-
let my_pwm = PWM::new(1, 127); // number depends on chip, etc.
69+
let my_pwm = Pwm::new(1, 127); // number depends on chip, etc.
7070
my_pwm.with_exported(|| {
7171
loop {
7272
pwm_increase_to_max(pwm, 1000, 20);

src/error.rs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright 2016, Paul Osborne <osbpau@gmail.com>
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
//
9+
// Portions of this implementation are based on work by Nat Pryce:
10+
// https://github.com/npryce/rusty-pi/blob/master/src/pi/gpio.rs
11+
12+
use std::convert;
13+
use std::fmt;
14+
use std::io;
15+
16+
#[derive(Debug)]
17+
pub enum Error {
18+
/// Simple IO error
19+
Io(io::Error),
20+
/// Read unusual data from sysfs file.
21+
Unexpected(String),
22+
}
23+
24+
impl ::std::error::Error for Error {
25+
fn description(&self) -> &str {
26+
match *self {
27+
Error::Io(ref e) => e.description(),
28+
Error::Unexpected(_) => "something unexpected",
29+
}
30+
}
31+
32+
fn cause(&self) -> Option<&::std::error::Error> {
33+
match *self {
34+
Error::Io(ref e) => Some(e),
35+
_ => None,
36+
}
37+
}
38+
}
39+
40+
impl fmt::Display for Error {
41+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
42+
match *self {
43+
Error::Io(ref e) => e.fmt(f),
44+
Error::Unexpected(ref s) => write!(f, "Unexpected: {}", s),
45+
}
46+
}
47+
}
48+
49+
50+
impl convert::From<io::Error> for Error {
51+
fn from(e: io::Error) -> Error {
52+
Error::Io(e)
53+
}
54+
}

src/lib.rs

Lines changed: 107 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,108 @@
1-
#[test]
2-
fn it_works() {
1+
// Copyright 2016, Paul Osborne <osbpau@gmail.com>
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// http://www.apache.org/license/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
//
9+
// Portions of this implementation are based on work by Nat Pryce:
10+
// https://github.com/npryce/rusty-pi/blob/master/src/pi/gpio.rs
11+
12+
#![crate_type = "lib"]
13+
#![crate_name = "sysfs_pwm"]
14+
15+
//! PWM access under Linux using the PWM sysfs interface
16+
17+
use std::io::prelude::*;
18+
use std::os::unix::prelude::*;
19+
use std::fs::File;
20+
use std::fs;
21+
22+
mod error;
23+
pub use error::Error;
24+
25+
#[derive(Debug)]
26+
pub struct PwmChip {
27+
chip: u32
28+
}
29+
30+
#[derive(Debug)]
31+
pub struct Pwm {
32+
chip: PwmChip,
33+
number: u32,
34+
}
35+
36+
pub type Result<T> = ::std::result::Result<T, error::Error>;
37+
38+
impl PwmChip {
39+
pub fn new(chip: u32) -> Result<PwmChip> {
40+
try!(fs::metadata(&format!("/sys/class/pwm/pwmchip{}", chip)));
41+
Ok(PwmChip { chip: chip })
42+
}
43+
44+
pub fn count(&self) -> Result<u32> {
45+
let npwm_path = format!("/sys/class/pwm/pwmchip{}/npwm", self.chip);
46+
let mut npwm_file = try!(File::open(&npwm_path));
47+
let mut s = String::new();
48+
try!(npwm_file.read_to_string(&mut s));
49+
match s.parse::<u32>() {
50+
Ok(n) => Ok(n),
51+
Err(_) => Err(Error::Unexpected(
52+
format!("Unexpected npwm contents: {:?}", s))),
53+
}
54+
}
55+
56+
pub fn export(&self, number: u32) -> Result<()> {
57+
// only export if not already exported
58+
if let Err(_) = fs::metadata(&format!("/sys/class/pwm/pwmchip{}/pwm{}", self.chip, number)) {
59+
let path = format!("/sys/class/pwm/pwmchip{}/export", self.chip);
60+
let mut export_file = try!(File::create(&path));
61+
let _ = export_file.write_all(format!("{}", number).as_bytes());
62+
}
63+
Ok(())
64+
}
65+
66+
pub fn unexport(&self, number: u32) -> Result<()> {
67+
if let Ok(_) = fs::metadata(&format!("/sys/class/pwm/pwmchip{}/pwm{}", self.chip, number)) {
68+
let path = format!("/sys/class/pwm/pwmchip{}/unexport", self.chip);
69+
let mut export_file = try!(File::create(&path));
70+
let _ = export_file.write_all(format!("{}", number).as_bytes());
71+
}
72+
Ok(())
73+
}
74+
}
75+
76+
impl Pwm {
77+
78+
/// Create a new Pwm wiht the provided chip/number
79+
///
80+
/// This function does not export the Pwm pin
81+
pub fn new(chip: u32, number: u32) -> Result<Pwm> {
82+
let chip: PwmChip = try!(PwmChip::new(chip));
83+
Ok(Pwm { chip: chip, number: number })
84+
}
85+
86+
/// Run a closure with the GPIO exported
87+
#[inline]
88+
pub fn with_exported<F>(&self, closure: F) -> Result<()> where
89+
F: FnOnce() -> Result<()>
90+
{
91+
try!(self.export());
92+
match closure() {
93+
Ok(()) => self.unexport(),
94+
Err(_) => self.unexport(),
95+
}
96+
}
97+
98+
/// Export the Pwm for use
99+
pub fn export(&self) -> Result<()> {
100+
self.chip.export(self.number)
101+
}
102+
103+
/// Unexport the PWM
104+
pub fn unexport(&self) -> Result<()> {
105+
self.chip.unexport(self.number)
106+
}
107+
3108
}

0 commit comments

Comments
 (0)