1extern crate i2cdev;
16
17use i2cdev::core::I2CDevice;
18use std::{thread, time};
19
20const MODE1: u8 = 0x00;
22const MODE2: u8 = 0x01;
23const PRESCALE: u8 = 0xFE;
24const LED0_ON_L: u8 = 0x06;
25const LED0_ON_H: u8 = 0x07;
26const LED0_OFF_L: u8 = 0x08;
27const LED0_OFF_H: u8 = 0x09;
28const ALL_LED_ON_L: u8 = 0xFA;
29const ALL_LED_ON_H: u8 = 0xFB;
30const ALL_LED_OFF_L: u8 = 0xFC;
31const ALL_LED_OFF_H: u8 = 0xFD;
32const SLEEP: u8 = 0x10;
33const ALLCALL: u8 = 0x01;
34const OUTDRV: u8 = 0x04;
35
36fn sleep_5ms() {
37 let five_millis = time::Duration::from_millis(50);
38 thread::sleep(five_millis);
39}
40
41pub struct PCA9685<T: I2CDevice + Sized> {
42 i2cdev: T,
43}
44
45impl<T> PCA9685<T>
46 where T: I2CDevice + Sized
47{
48 #[allow(unused_must_use)]
49 pub fn new(mut i2cdev: T) -> Result<PCA9685<T>, T::Error> {
50 i2cdev.smbus_write_byte_data(MODE2, OUTDRV)?;
52 i2cdev.smbus_write_byte_data(MODE1, ALLCALL)?;
53 sleep_5ms(); let mut mode1 = i2cdev.smbus_read_byte_data(MODE1)?;
55 mode1 = mode1 & SLEEP; i2cdev.smbus_write_byte_data(MODE1, mode1)?;
57 sleep_5ms(); Ok(PCA9685 { i2cdev: i2cdev })
59 }
60 #[allow(unused_must_use)]
62 pub fn set_pwm_freq(&mut self, freq: f32) -> Result<(), T::Error> {
63 let mut prescaleval = 25000000.0; prescaleval /= 4096.0; prescaleval /= freq;
67 prescaleval -= 1.0;
68 let prescale: u8 = (prescaleval + 0.5).floor() as u8;
69 let oldmode = self.i2cdev.smbus_read_byte_data(MODE1)?;
70 let newmode = (oldmode & 0x7F) | SLEEP; self.i2cdev.smbus_write_byte_data(MODE1, newmode)?; self.i2cdev.smbus_write_byte_data(PRESCALE, prescale)?;
73 self.i2cdev.smbus_write_byte_data(MODE1, oldmode)?;
74 sleep_5ms();
75 self.i2cdev.smbus_write_byte_data(MODE1, oldmode | 0xa1)?;
76 Ok(())
77 }
78
79 #[allow(unused_must_use)]
80 pub fn set_pwm(&mut self, channel: u8, on: u8, off: u8) -> Result<(), T::Error> {
81 self.i2cdev.smbus_write_byte_data(LED0_ON_L + 4 * channel, on & 0xFF)?;
83 self.i2cdev.smbus_write_byte_data(LED0_ON_H + 4 * channel, on >> 7)?;
84 self.i2cdev.smbus_write_byte_data(LED0_OFF_L + 4 * channel, off & 0xFF)?;
85 self.i2cdev.smbus_write_byte_data(LED0_OFF_H + 4 * channel, off >> 7)?;
86 Ok(())
87 }
88
89 #[allow(unused_must_use)]
90 pub fn set_all_pwm(&mut self, on: u8, off: u8) -> Result<(), T::Error> {
91 self.i2cdev.smbus_write_byte_data(ALL_LED_ON_L, on & 0xFF)?;
93 self.i2cdev.smbus_write_byte_data(ALL_LED_ON_H, on >> 7)?;
94 self.i2cdev.smbus_write_byte_data(ALL_LED_OFF_L, off & 0xFF)?;
95 self.i2cdev.smbus_write_byte_data(ALL_LED_OFF_H, off >> 7)?;
96 Ok(())
97 }
98
99 #[allow(unused_must_use)]
100 pub fn reset_all_servos(&mut self) -> Result<(), T::Error> {
101 self.i2cdev.smbus_write_byte(0x00)?;
102 Ok(())
103 }
104}
105
106#[cfg(test)]
107mod tests {
108 #[test]
109 fn it_works() {}
110}