From d191072a3c21594abceba58fd16f72e5a16bf44f Mon Sep 17 00:00:00 2001 From: Paul van Tilburg Date: Fri, 15 Mar 2019 22:22:20 +0100 Subject: [PATCH] Add accelerometer support --- src/led.rs | 20 ++++++++++++++ src/main.rs | 78 +++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 90 insertions(+), 8 deletions(-) diff --git a/src/led.rs b/src/led.rs index af5c953..5c26ecb 100644 --- a/src/led.rs +++ b/src/led.rs @@ -22,6 +22,7 @@ impl Direction { pub enum Mode { Off, Cycle, + Accelerometer } pub struct LedRing { @@ -47,6 +48,10 @@ impl LedRing { self.mode = Mode::Cycle; } + pub fn enable_accel(&mut self) { + self.mode = Mode::Accelerometer; + } + pub fn disable(&mut self) { self.mode = Mode::Off; } @@ -55,6 +60,10 @@ impl LedRing { self.mode == Mode::Cycle } + pub fn is_mode_accel(&self) -> bool { + self.mode == Mode::Accelerometer + } + pub fn reverse(&mut self) { self.direction = self.direction.flip(); } @@ -82,4 +91,15 @@ impl LedRing { led.set_low(); } } + + pub fn set_directions(&mut self, directions: [bool; 4]) { + for setting in self.leds.iter_mut().zip(directions.iter()) { + let (led, on_off) = setting; + if *on_off { + led.set_high(); + } else { + led.set_low(); + } + } + } } diff --git a/src/main.rs b/src/main.rs index b8364c3..da2780f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,16 +11,22 @@ use crate::led::{Led, LedRing}; use core::fmt::Write; use cortex_m_semihosting::hprintln; use hal::block; -use hal::gpio::{Edge, ExtiPin, Floating, Input}; +use hal::gpio::{Alternate, Edge, ExtiPin, Floating, Input, Output, PushPull, AF5}; use hal::prelude::*; use hal::serial::{self, config::Config as SerialConfig, Serial}; -use hal::stm32::{EXTI, USART2}; +use hal::spi::{Mode, Phase, Polarity, Spi}; +use hal::stm32::{EXTI, SPI1, USART2}; use heapless::consts::U8; use heapless::Vec; use rtfm::app; +type Accelerometer = hal::spi::Spi; +type AccelerometerCs = hal::gpio::gpioe::PE3>; type SerialTx = hal::serial::Tx; type SerialRx = hal::serial::Rx; +type Spi1Sck = hal::gpio::gpioa::PA5>; +type Spi1Miso = hal::gpio::gpioa::PA6>; +type Spi1Mosi = hal::gpio::gpioa::PA7>; type UserButton = hal::gpio::gpioa::PA0>; #[app(device = hal::stm32)] @@ -31,8 +37,10 @@ const APP: () = { static mut exti: EXTI = (); static mut serial_rx: SerialRx = (); static mut serial_tx: SerialTx = (); + static mut accel: Accelerometer = (); + static mut accel_cs: AccelerometerCs = (); - #[init(spawn = [cycle_leds])] + #[init(spawn = [accel_leds, cycle_leds])] fn init() -> init::LateResources { // Set up the LED ring and spawn the LEDs switch task. let gpiod = device.GPIOD.split(); @@ -45,6 +53,8 @@ const APP: () = { let led_ring = LedRing::from(leds); if led_ring.is_mode_cycle() { spawn.cycle_leds().unwrap(); + } else if led_ring.is_mode_accel() { + spawn.accel_leds().unwrap(); } // Set up the EXTI0 interrupt for the user button. @@ -67,6 +77,24 @@ const APP: () = { // Set up the serial interface command buffer. let buffer = Vec::new(); + // Set up the accelerometer. + let sck = gpioa.pa5.into_alternate_af5(); + let miso = gpioa.pa6.into_alternate_af5(); + let mosi = gpioa.pa7.into_alternate_af5(); + let mode = Mode { + polarity: Polarity::IdleHigh, + phase: Phase::CaptureOnSecondTransition, + }; + let mut accel = Spi::spi1(device.SPI1, (sck, miso, mosi), mode, 100.hz(), clocks); + + let gpioe = device.GPIOE.split(); + let mut accel_cs = gpioe.pe3.into_push_pull_output(); + + // Initialize the accelerometer. + accel_cs.set_low(); + let _ = accel.transfer(&mut [0x20, 0b01000111]).unwrap(); + accel_cs.set_high(); + // Output to the serial interface that initialisation is finished. writeln!(serial_tx, "init\r").unwrap(); @@ -77,22 +105,51 @@ const APP: () = { led_ring, serial_tx, serial_rx, + accel, + accel_cs, } } - #[task(schedule = [switch_leds], resources = [led_ring])] - fn switch_leds() { + #[task(schedule = [cycle_leds], resources = [led_ring])] + fn cycle_leds() { resources.led_ring.lock(|led_ring| { if led_ring.is_mode_cycle() { led_ring.advance(); schedule - .switch_leds(scheduled + LedRing::PERIOD.cycles()) + .cycle_leds(scheduled + LedRing::PERIOD.cycles()) .unwrap(); } }); } - #[interrupt(binds = EXTI0, resources = [button, exti, led_cycle, serial_tx])] + #[task(schedule = [accel_leds], resources = [accel, accel_cs, led_ring, serial_tx])] + fn accel_leds() { + resources.accel_cs.set_low(); + let read_command = (1 << 7) | (1 << 6) | 0x29; + let mut commands = [read_command, 0x0, 0x0, 0x0]; + let result = resources.accel.transfer(&mut commands[..]).unwrap(); + let acc_x = result[1] as i8; + let acc_y = result[3] as i8; + resources.accel_cs.set_high(); + + if acc_x == 0 && acc_y == 0 { + resources + .serial_tx + .lock(|serial_tx| + writeln!(serial_tx, "level\r").unwrap() + ); + } + + resources.led_ring.lock(|led_ring| { + if led_ring.is_mode_accel() { + let directions = [acc_y < 0, acc_x < 0, acc_y > 0, acc_x > 0]; + led_ring.set_directions(directions); + schedule.accel_leds(scheduled + LedRing::PERIOD.cycles()).unwrap(); + } + }) + } + + #[interrupt(binds = EXTI0, resources = [button, exti, led_ring, serial_tx])] fn button_pressed() { resources.led_ring.lock(|led_ring| led_ring.reverse()); @@ -108,7 +165,7 @@ const APP: () = { binds = USART2, priority = 2, resources = [buffer, led_ring, serial_rx, serial_tx], - spawn = [cycle_leds] + spawn = [accel_leds, cycle_leds] )] fn handle_serial() { let buffer = resources.buffer; @@ -133,6 +190,10 @@ const APP: () = { resources.led_ring.enable_cycle(); spawn.cycle_leds().unwrap(); } + b"accel" => { + resources.led_ring.enable_accel(); + spawn.accel_leds().unwrap(); + } b"off" => { resources.led_ring.disable(); resources.led_ring.all_off(); @@ -163,5 +224,6 @@ const APP: () = { extern "C" { fn TIM2(); + fn TIM3(); } };