@@ -18,14 +18,16 @@ use std::io::prelude::*;
1818use std:: os:: unix:: prelude:: * ;
1919use std:: fs:: File ;
2020use std:: fs;
21+ use std:: str:: FromStr ;
2122use std:: cmp:: { min, max} ;
23+ use std:: path:: Path ;
2224
2325mod error;
2426pub use error:: Error ;
2527
2628#[ derive( Debug ) ]
2729pub struct PwmChip {
28- chip : u32 ,
30+ pub number : u32 ,
2931}
3032
3133#[ derive( Debug ) ]
@@ -42,14 +44,41 @@ pub enum Polarity {
4244
4345pub 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+
4574impl 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