Skip to content

Commit

Permalink
smbus: fix issue rust-embedded#1 and expose smbus publically
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
posborne committed Sep 13, 2015
1 parent 771a12f commit fe61301
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 16 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,7 @@
# Generated by Cargo
Cargo.lock
/target/

# TAGS
GPATH
*TAGS
48 changes: 32 additions & 16 deletions examples/nunchuck.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<NunchuckReading> {
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,
})
}
}
}
Expand All @@ -76,7 +81,9 @@ enum NunchuckInitError {

#[derive(Debug)]
enum NunchuckReadError {
I2CError(I2CError),
IOError(io::Error),
ParsingError,
}

impl Nunchuck {
Expand All @@ -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<NunchuckReading, NunchuckReadError> {
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)),
}
}
Expand Down
1 change: 1 addition & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,4 @@ extern crate byteorder;

mod ffi;
pub mod core;
pub mod smbus;
1 change: 1 addition & 0 deletions src/smbus.rs
Original file line number Diff line number Diff line change
@@ -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
Expand Down

0 comments on commit fe61301

Please sign in to comment.