Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
prakhars0206 authored and ishmis03 committed Nov 16, 2024
1 parent ed33d6c commit ac0ebdc
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 9 deletions.
16 changes: 8 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion boards/stm32l476rg/src/io.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub mod adc;
pub mod gpio;
pub mod i2c;
pub mod adc;
127 changes: 127 additions & 0 deletions lib/sensors/src/optical_flow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
use crate::spi::HypedSpi;
use std::time::{Duration, Instant, SystemTime, UNIX_EPOCH};
use byteorder::{LittleEndian, ReadBytesExt};
use std::thread::sleep;
use serde::{Serialize, Deserialize};
use serde_json::json;


// implement get_motion function first
// add readByteFromRegister (?) function to HypedSPI trait which takes register address and gives data

const REG_MOTION_BURST: u8 = 0x16;
const TIMEOUT: Duration = Duration::from_secs(5);


pub struct PMW3901<SPI> {
spi: SPI,

}

impl<SPI> PMW3901<SPI>
where
SPI: HypedSpi,
{


pub fn new(spi: SPI) -> Self {
PMW3901 { spi }
}

// **ATTEMPTED PYTHON IMPLEMENTATION OF get_motion**
pub fn get_motion(&mut self) -> Result<(i16, i16), &'static str>{
let start = Instant::now();


while start.elapsed() < TIMEOUT {
// Send burst read command and read 12 bytes
let mut data = [0u8; 13]; // Includes the command byte
data[0] = REG_MOTION_BURST; // first element in data is the register
self.spi.read(&mut data).map_err(|_| "SPI read failed")?; //read data using HypedSpi trait

// Parse the response data
let mut cursor = &data[1..]; //slice data and use cursor to go through the data
let _ = cursor.read_u8().unwrap(); // read each byte from cursor and assign it to variables
let dr = cursor.read_u8().unwrap();
let obs = cursor.read_u8().unwrap();
let x = cursor.read_i16::<LittleEndian>().unwrap(); // x and y value is what we need and little endian is used to make sure bytes are ordered ith LSB first
let y = cursor.read_i16::<LittleEndian>().unwrap(); // LittleEndian takes (advances) 2 bytes from cursor
let quality = cursor.read_u8().unwrap();
let raw_sum = cursor.read_u8().unwrap();
let raw_max = cursor.read_u8().unwrap();
let raw_min = cursor.read_u8().unwrap();
let shutter_upper = cursor.read_u8().unwrap();
let shutter_lower = cursor.read_u8().unwrap();

if (dr & 0b1000_0000) != 0 && (quality >= 0x19 || shutter_upper != 0x1F) {
return Ok((x, y)); // Return delta x and y if valid
}

// Delay before retrying
sleep(Duration::from_millis(10));

}

Err("Timed out waiting for motion data")
}

}


// the # implements the Serialize trait from the serde crate for the strcuts. this is apparently needed to convert strcut to json
#[derive(Serialize)]
struct Measurement {
header: Header,
payload: Payload,
}

#[derive(Serialize)]
struct Header {
timestamp: u64,
priority: u8,
}

#[derive(Serialize)]
struct Payload {
x: i16,
y: i16,
}


// Make main function with flexible error handling
pub fn main() -> Result<(), Box<dyn std::error::Error>> {


let spi = HypedSPI::new() // spi implementation?
let mut sensor = PMW3901::new(spi);


// While loop implementation from python code
loop {

// Get motion data
let (x, y) = sensor.get_motion()?;

// Prepare measurement data
let measurement = Measurement {
header: Header {
timestamp: SystemTime::now()
.duration_since(UNIX_EPOCH)? // Get time in secs from epoch as in the python code
.as_secs(),
priority: 1,
},
payload: Payload { x, y },
};

// Serialize measurement data to JSON
let measurement_data = serde_json::to_string(&measurement)?;

// Print payload
//println!("{}", measurement_data);


// delay
sleep(Duration::from_millis(50));

}
}

0 comments on commit ac0ebdc

Please sign in to comment.