1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
//! `saberrs` is a library for interfacing with [Dimension Engineering]
//! Sabertooth motor driver.
//!
//! Currently only the Sabertooth 2x32 is supported.
//!
//! # Simple usage
//!
//! ```rust
//! # use saberrs::Result;
//! use saberrs::sabertooth2x32::{Sabertooth2x32, PacketSerial};
//!
//! # fn example() -> Result<()> {
//! // Create a handle. This will use "PacketSerial" protocol.
//! let mut saber = PacketSerial::new("/dev/ttyS0")?;
//!
//! // Go forward at half-speed (50.0%)
//! saber.set_drive(0.5)?;
//! saber.set_turn(0.0)?;
//!
//! // Request the battery voltage from motor 1.
//! let vbat : f32 = saber.get_voltage(1)?;
//!
//! // Stop the motors
//! saber.stop_motors()?;
//!
//! # Ok(())
//! # }
//! ```
//!
//! Other protocol variants can be used:
//!
//! ```rust
//! use saberrs::sabertooth2x32::{Sabertooth2x32, PacketSerial, PacketType, PlainText};
//! # use saberrs::Result;
//!
//! # fn example() -> Result<()> {
//! // "PacketSerial" with specified address and frame protection type.
//! let mut saber = PacketSerial::new("/dev/ttyS0")?
//!     .with_packet_type(PacketType::Checksum)
//!     .with_address(129);
//!
//! // "PlainText" protocol
//! let mut sabertext = PlainText::new("/dev/ttyS1")?;
//! # Ok(())
//! # }
//! ```
//!
//! # Customizing the IO: the `SabertoothSerial` trait
//!
//! The handles rely on the trait [SabertoothSerial], which abstract the
//! low-level IO communication with the device.
//!
//! By default, the library provides [SabertoothPort] and
//! [SabertoothPortShared]. In most cases the application writer shouldn't need
//! to care about those, but they may be used for applying custom baud rates or
//! timeout values for example.
//!
//! [SabertoothSerial] can be implemented manually for even more customization.
//! For example stubs can be implemented for debugging purpose:
//!
//! ```rust
//! use std::time::Duration;
//! use std::io::{self, Read, Write};
//! use saberrs::{SabertoothSerial};
//!
//! struct SerialStub {
//!     timeout: Duration,
//!     baudrate: u32,
//! }
//!
//! impl SerialStub {
//!     pub fn new() -> Self {
//!         SerialStub {
//!             timeout: Duration::from_millis(100),
//!             baudrate: 9600,
//!         }
//!     }
//! }
//!
//! impl Read for SerialStub {
//!     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
//!         println!("SerialStub.read()");
//!         Ok(0)
//!     }
//! }
//!
//! impl Write for SerialStub {
//!     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
//!         println!("SerialStub.write({:?})", buf);
//!         Ok(buf.len())
//!     }
//!
//!     fn flush(&mut self) -> io::Result<()> { Ok(()) }
//! }
//!
//! impl SabertoothSerial for SerialStub {
//!     fn set_timeout(&mut self, timeout: Duration) -> saberrs::Result<()> {
//!         println!("SerialStub.set_timeout({:?})", timeout);
//!         self.timeout = timeout;
//!         Ok(())
//!     }
//!
//!     fn timeout(&self) -> Duration {
//!         println!("SerialStub.timeout() -> {:?}", self.timeout);
//!         self.timeout
//!     }
//!
//!     fn set_baud_rate(&mut self, baud_rate: u32) -> saberrs::Result<()> {
//!         println!("SerialStub.set_baudrate({})", baud_rate);
//!         self.baudrate = baud_rate;
//!         Ok(())
//!     }
//!
//!     fn baud_rate(&self) -> saberrs::Result<u32> {
//!         println!("SerialStub.baud_rate() -> {}", self.baudrate);
//!         Ok(self.baudrate)
//!     }
//!
//!     fn clear_all(&self) -> saberrs::Result<()> { Ok(()) }
//! }
//! ```
//!
//!
//! # Features and dependencies
//!
//! Features:
//!
//! - `serialport`, enabled by default, allows the usage of the crate
//! [serialport] for providing [SabertoothPort] and [SabertoothPortShared].
//! If this feature is disabled [SabertoothSerial] needs to be implemented
//! manually.
//!
//! Dependencies:
//!
//! - [serialport] for the `serialport` feature.
//! - [log] for emitting logs.
//!
//! # Disclaimer
//!
//! This library is not affiliated or associated in any way with Dimension Engineering.
//!
//! All product and company names are trademarks or registered trademarks of
//! their respective holders. Use of them does not imply any affiliation with or
//! endorsement by them.
//!
//! [Dimension Engineering]: https://www.dimensionengineering.com
//! [Sabertooth 2x32]: https://www.dimensionengineering.com/products/sabertooth2x32
//! [SabertoothSerial]: trait.SabertoothSerial.html
//! [SabertoothPort]: struct.SabertoothPort.html
//! [SabertoothPortShared]: struct.SabertoothPortShared.html
//! [serialport]: https://crates.io/crates/serialport
//! [log]: https://crates.io/crates/log

pub use error::{Error, ErrorKind, Result};
pub use port::SabertoothSerial;

#[cfg(feature = "serialport")]
pub use port::sabertoothport::{SabertoothPort, SabertoothPortShared};

#[macro_use]
mod utils;

mod error;
mod port;

/// Interface for the [Sabertooth 2x32].
///
/// [Sabertooth 2x32]: https://www.dimensionengineering.com/products/sabertooth2x32
pub mod sabertooth2x32;