From fe61301095f42e2beedccffac198dbf65f014def Mon Sep 17 00:00:00 2001 From: Paul Osborne Date: Sat, 12 Sep 2015 22:22:28 -0500 Subject: [PATCH] smbus: fix issue #1 and expose smbus publically Previously, there were some bugs with the SMBus implementation and it was not actually exposed at all. Now, the nunchuck example uses the SMBus funtions where it can. --- .gitignore | 4 ++++ examples/nunchuck.rs | 48 +++++++++++++++++++++++++++++--------------- src/lib.rs | 1 + src/smbus.rs | 1 + 4 files changed, 38 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index f857248d..f7f0ce67 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,7 @@ # Generated by Cargo Cargo.lock /target/ + +# TAGS +GPATH +*TAGS diff --git a/examples/nunchuck.rs b/examples/nunchuck.rs index 121f0faf..7fae7ac4 100644 --- a/examples/nunchuck.rs +++ b/examples/nunchuck.rs @@ -12,11 +12,12 @@ extern crate i2cdev; extern crate docopt; use i2cdev::core::*; +use i2cdev::smbus::*; +use std::io; use std::io::prelude::*; use std::env::args; use docopt::Docopt; use std::thread; -use std::io; use std::path::Path; const NUNCHUCK_SLAVE_ADDR: u16 = 0x52; @@ -46,15 +47,19 @@ struct NunchuckReading { } impl NunchuckReading { - fn from_data(data: &[u8; 6]) -> NunchuckReading { - NunchuckReading { - joystick_x: data[0], - joystick_y: data[1], - accel_x: (data[2] as u16) << 2 | ((data[5] as u16 >> 6) & 0b11), - accel_y: (data[3] as u16) << 2 | ((data[5] as u16 >> 4) & 0b11), - accel_z: (data[4] as u16) << 2 | ((data[5] as u16 >> 2) & 0b11), - c_button_pressed: (data[5] & 0b10) == 0, - z_button_pressed: (data[5] & 0b01) == 0, + fn from_data(data: &[u8]) -> Option { + if data.len() < 6 { + None + } else { + Some(NunchuckReading { + joystick_x: data[0], + joystick_y: data[1], + accel_x: (data[2] as u16) << 2 | ((data[5] as u16 >> 6) & 0b11), + accel_y: (data[3] as u16) << 2 | ((data[5] as u16 >> 4) & 0b11), + accel_z: (data[4] as u16) << 2 | ((data[5] as u16 >> 2) & 0b11), + c_button_pressed: (data[5] & 0b10) == 0, + z_button_pressed: (data[5] & 0b01) == 0, + }) } } } @@ -76,7 +81,9 @@ enum NunchuckInitError { #[derive(Debug)] enum NunchuckReadError { + I2CError(I2CError), IOError(io::Error), + ParsingError, } impl Nunchuck { @@ -95,21 +102,30 @@ impl Nunchuck { /// Send the init sequence to the Wii Nunchuck pub fn init(&mut self) -> Result<(), NunchuckInitError> { - try!(self.i2cdev.write_all(&[0xF0, 0x55]) + // These registers must be written; the documentation is a bit + // lacking but it appears this is some kind of handshake to + // perform unencrypted data tranfers + try!(self.i2cdev.smbus_write_byte_data(0xF0, 0x55) .or_else(|_| Err(NunchuckInitError::WriteFailed))); - try!(self.i2cdev.write_all(&[0xFB, 0x00]) + try!(self.i2cdev.smbus_write_byte_data(0xFB, 0x00) .or_else(|_| Err(NunchuckInitError::WriteFailed))); - thread::sleep_ms(100); Ok(()) } pub fn read(&mut self) -> Result { let mut buf: [u8; 6] = [0; 6]; - try!(self.i2cdev.write_all(&[0x00]) - .or_else(|e| Err(NunchuckReadError::IOError(e)))); + + // tell the nunchuck to prepare a sample + try!(self.i2cdev.smbus_write_byte(0x00) + .or_else(|e| Err(NunchuckReadError::I2CError(e)))); + + // now, read it! thread::sleep_ms(10); match self.i2cdev.read(&mut buf) { - Ok(_len) => Ok(NunchuckReading::from_data(&buf)), + Ok(_len) => match NunchuckReading::from_data(&buf) { + Some(reading) => Ok(reading), + None => Err(NunchuckReadError::ParsingError), + }, Err(err) => Err(NunchuckReadError::IOError(err)), } } diff --git a/src/lib.rs b/src/lib.rs index 6d32406a..db5ba4cb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,3 +23,4 @@ extern crate byteorder; mod ffi; pub mod core; +pub mod smbus; diff --git a/src/smbus.rs b/src/smbus.rs index b7ec9712..32241c94 100644 --- a/src/smbus.rs +++ b/src/smbus.rs @@ -1,5 +1,6 @@ use ffi; use core::*; +use std::os::unix::prelude::*; pub trait I2CSMBus { /// This sends a single bit to the device, at the place of the Rd/Wr bit