qik_rs/
lib.rs

1use std::thread::sleep_ms;
2use std::time::Duration;
3
4//extern crate sysfs_gpio;
5//
6//use sysfs_gpio::{Direction, Pin};
7
8extern crate serial;
9
10use std::io::prelude::*;
11use self::serial::prelude::*;
12use self::serial::posix::TTYPort;
13
14#[allow(non_camel_case_types)]
15pub enum Motor {
16    M0,
17    M1
18}
19
20#[allow(non_camel_case_types)]
21pub enum ConfigParam {
22    DEVICE_ID, //0,
23    PWM_PARAMETER, //1,
24    SHUT_DOWN_MOTORS_ON_ERROR, //2,
25    SERIAL_TIMEOUT, //3,
26    MOTOR_M0_ACCELERATION, //4,
27    MOTOR_M1_ACCELERATION, //5,
28    MOTOR_M0_BRAKE_DURATION, //6,
29    MOTOR_M1_BRAKE_DURATION, //7,
30    MOTOR_M0_CURRENT_LIMIT_DIV_2, //8,
31    MOTOR_M1_CURRENT_LIMIT_DIV_2, //9,
32    MOTOR_M0_CURRENT_LIMIT_RESPONSE, //10,
33    MOTOR_M1_CURRENT_LIMIT_RESPONSE, //11,
34}
35
36#[allow(non_camel_case_types)]
37enum Command {
38    GET_FIRMWARE_VERSION,
39    GET_ERROR_BYTE,
40    GET_CONFIGURATION_PARAMETER,
41    SET_CONFIGURATION_PARAMETER,
42
43    MOTOR_M0_FORWARD,
44    MOTOR_M0_FORWARD_8_BIT,
45    MOTOR_M0_REVERSE,
46    MOTOR_M0_REVERSE_8_BIT,
47    MOTOR_M1_FORWARD,
48    MOTOR_M1_FORWARD_8_BIT,
49    MOTOR_M1_REVERSE,
50    MOTOR_M1_REVERSE_8_BIT,
51
52    // 2s9v1 only
53    MOTOR_M0_COAST,
54    MOTOR_M1_COAST,
55
56    // 2s12v10 only
57    MOTOR_M0_BRAKE,
58    MOTOR_M1_BRAKE,
59    GET_MOTOR_M0_CURRENT,
60    GET_MOTOR_M1_CURRENT,
61    GET_MOTOR_M0_SPEED,
62    GET_MOTOR_M1_SPEED,
63}
64
65fn get_cmd_byte(cmd: Command) -> u8 {
66    use self::Command::*;
67    match cmd {
68        // commons
69        GET_FIRMWARE_VERSION => 0x81,
70        GET_ERROR_BYTE => 0x82,
71        GET_CONFIGURATION_PARAMETER => 0x83,
72        SET_CONFIGURATION_PARAMETER  => 0x84,
73        MOTOR_M0_FORWARD => 0x88,
74        MOTOR_M0_FORWARD_8_BIT => 0x89,
75        MOTOR_M0_REVERSE => 0x8A,
76        MOTOR_M0_REVERSE_8_BIT => 0x8B,
77        MOTOR_M1_FORWARD => 0x8C,
78        MOTOR_M1_FORWARD_8_BIT => 0x8D,
79        MOTOR_M1_REVERSE => 0x8E,
80        MOTOR_M1_REVERSE_8_BIT => 0x8F,
81        // 2s9v1 only
82        MOTOR_M0_COAST => 0x86,
83        MOTOR_M1_COAST => 0x87,
84        // 2s12v10 only
85        MOTOR_M0_BRAKE => 0x86,
86        MOTOR_M1_BRAKE => 0x87,
87        GET_MOTOR_M0_CURRENT => 0x90,
88        GET_MOTOR_M1_CURRENT => 0x91,
89        GET_MOTOR_M0_SPEED => 0x92,
90        GET_MOTOR_M1_SPEED => 0x93,
91    }
92}
93
94
95fn get_config_param_byte(p: ConfigParam) -> u8 {
96    use self::ConfigParam::*;
97    match p {
98        DEVICE_ID => 0,
99        PWM_PARAMETER => 1,
100        SHUT_DOWN_MOTORS_ON_ERROR => 2,
101        SERIAL_TIMEOUT => 3,
102        MOTOR_M0_ACCELERATION => 4,
103        MOTOR_M1_ACCELERATION => 5,
104        MOTOR_M0_BRAKE_DURATION => 6,
105        MOTOR_M1_BRAKE_DURATION => 7,
106        MOTOR_M0_CURRENT_LIMIT_DIV_2 => 8,
107        MOTOR_M1_CURRENT_LIMIT_DIV_2 => 9,
108        MOTOR_M0_CURRENT_LIMIT_RESPONSE => 10,
109        MOTOR_M1_CURRENT_LIMIT_RESPONSE => 11,
110    }
111}
112
113
114pub struct Qik {
115    device: String,
116//    reset_pin: Pin,
117    port: TTYPort,
118}
119
120impl Qik {
121
122    pub fn new(device: String, reset_pin: u8) -> Self {
123
124        let mut port = serial::open(&device).unwrap();
125
126        port.reconfigure(&|settings| {
127            settings.set_baud_rate(serial::Baud9600).unwrap();
128            settings.set_char_size(serial::Bits8);
129            settings.set_parity(serial::ParityNone);
130            settings.set_stop_bits(serial::Stop1);
131            settings.set_flow_control(serial::FlowNone);
132            Ok(())
133        }).unwrap();
134
135        port.set_timeout(Duration::from_millis(5000)).unwrap();
136
137        Qik { device: device, /*reset_pin: Pin::new(reset_pin),*/ port: port }
138    }
139
140    pub fn init(&mut self) {
141//        self.reset_pin.with_exported(|| {
142//            self.reset_pin.set_value(0).unwrap();
143//            self.reset_pin.set_direction(Direction::Out).unwrap();
144//            thread::sleep(Duration::from_millis(1));
145//            self.reset_pin.set_direction(Direction::In).unwrap();
146//            thread::sleep(Duration::from_millis(10));
147//        });
148
149        // begin(speed); //TODO: do we need to set up serial port here?
150        self.write_byte(0xAA);
151    }
152
153    pub fn get_firmware_version(&mut self) -> u8 {
154        let buf: Vec<u8> = vec![ get_cmd_byte(Command::GET_FIRMWARE_VERSION) ];
155        self.write(&buf);
156        self.read_byte()
157    }
158
159    pub fn get_config(&mut self, p: ConfigParam) -> u8 {
160        let cmd: Vec<u8> = vec![
161            get_cmd_byte(Command::GET_CONFIGURATION_PARAMETER),
162            get_config_param_byte(p)
163        ];
164        self.write(&cmd);
165        self.read_byte()
166    }
167
168    pub fn set_config(&mut self, p: ConfigParam, v: u8) -> u8 {
169        let cmd: Vec<u8> = vec![
170            get_cmd_byte(Command::SET_CONFIGURATION_PARAMETER),
171            get_config_param_byte(p),
172            v,
173            0x55,
174            0x2A
175        ];
176        self.write(&cmd);
177        self.read_byte()
178    }
179
180    pub fn get_error(&mut self) -> u8 {
181        let buf: Vec<u8> = vec![ get_cmd_byte(Command::GET_ERROR_BYTE) ];
182        self.write(&buf);
183        self.read_byte()
184    }
185
186    pub fn set_speed(&mut self, m: Motor, speed: i8) {
187        if speed >= 0 {
188            // forward
189            let cmd: Vec<u8> = vec![
190                get_cmd_byte(match m {
191                    Motor::M0 => Command::MOTOR_M0_FORWARD_8_BIT,
192                    Motor::M1 => Command::MOTOR_M1_FORWARD_8_BIT
193                }),
194                speed as u8
195            ];
196            self.write(&cmd);
197        } else {
198            // reverse
199            let cmd: Vec<u8> = vec![
200                get_cmd_byte(match m {
201                    Motor::M0 => Command::MOTOR_M0_REVERSE_8_BIT,
202                    Motor::M1 => Command::MOTOR_M1_REVERSE_8_BIT
203                }),
204                (0-speed) as u8
205            ];
206            self.write(&cmd);
207        }
208    }
209
210    /// 2s9v1 only
211    pub fn coast(&mut self, m: Motor) {
212        let buf: Vec<u8> = vec![ get_cmd_byte(match m {
213            Motor::M0 => Command::MOTOR_M0_COAST,
214            Motor::M1 => Command::MOTOR_M1_COAST
215        })];
216        self.write(&buf);
217    }
218
219    /// 2s12v10 only
220    pub fn set_brake(&mut self, m: Motor, v: u8) {
221        assert!(v<128);
222        let cmd: Vec<u8> = vec![
223            get_cmd_byte(match m {
224                Motor::M0 => Command::MOTOR_M0_BRAKE,
225                Motor::M1 => Command::MOTOR_M1_BRAKE
226            }),
227            v
228        ];
229        self.write(&cmd);
230    }
231
232    /// 2s12v10 only
233    pub fn get_speed(&mut self, m: Motor) -> u8 {
234        self.write_byte(get_cmd_byte(match m {
235            Motor::M0 => Command::GET_MOTOR_M0_SPEED,
236            Motor::M1 => Command::GET_MOTOR_M1_SPEED
237        }));
238        self.read_byte()
239    }
240
241    /// 2s12v10 only
242    pub fn get_current(&mut self, m: Motor) -> u8 {
243        let buf: Vec<u8> = vec![ get_cmd_byte(match m {
244            Motor::M0 => Command::GET_MOTOR_M0_CURRENT,
245            Motor::M1 => Command::GET_MOTOR_M1_CURRENT
246        })];
247        self.write(&buf);
248        self.read_byte()
249    }
250
251    /// 2s12v10 only
252    pub fn get_current_milliamps(&mut self, m: Motor) -> u32 {
253        self.get_current(m) as u32 * 150
254    }
255
256    /// writes a single byte to the serial port
257    fn write_byte(&mut self, b: u8) {
258        let buf: Vec<u8> = vec![ b ];
259        self.write(&buf);
260    }
261
262    /// writes a byte buffer to the serial port
263    fn write(&mut self, buf: &[u8]) {
264        self.port.write_all(buf).unwrap();
265    }
266
267    /// reads a single bytes from the serial port
268    fn read_byte(&mut self) -> u8 {
269        let buf = self.read(1);
270        buf[0]
271    }
272
273    /// reads varible number of bytes from the serial port
274    fn read(&mut self, n: usize) -> Vec<u8> {
275        let mut buf = vec![0_u8; n];
276        self.port.read_exact(buf.as_mut()).unwrap();
277        buf
278    }
279
280}