qei 1.0.2

A wrapper that allows to extend quadratic encoder interface (QEI)
Documentation
//! Shows how to use a QEI wrapper on an stm32f103xx.

#![no_main] //  Don't use the Rust standard bootstrap. We will provide our own.
#![no_std] //  Don't use the Rust standard library. We are building a binary that can run on its own.

extern crate cortex_m; //  Low-level functions for ARM Cortex-M3 processor in STM32 Blue Pill.
#[macro_use(entry, exception)] //  Import macros from the following crates,
extern crate cortex_m_rt; //  Startup and runtime functions for ARM Cortex-M3.
extern crate cortex_m_semihosting; //  Debug console functions for ARM Cortex-M3.
extern crate panic_semihosting; //  Panic reporting functions, which transmit to the debug console.
extern crate stm32f103xx_hal as bluepill_hal; //  Hardware Abstraction Layer (HAL) for STM32 Blue Pill.
#[macro_use]
extern crate stm32f103xx;
extern crate nb;
extern crate embedded_hal;
extern crate pid_control;
extern crate qei;

use cortex_m::Peripherals as CortexPeripherals;

use bluepill_hal::prelude::*; //  Define HAL traits.
use bluepill_hal::qei::Qei;
use bluepill_hal::stm32f103xx as f103;
use bluepill_hal::stm32f103xx::Peripherals;

use core::fmt::Write; //  Provides writeln() function for debug console output.
use cortex_m_rt::ExceptionFrame; //  Stack frame for exception handling.
use cortex_m_semihosting::hio; //  For displaying messages on the debug console. //  Clocks, flash memory, GPIO for the STM32 Blue Pill.

use f103::Interrupt;

use qei::QeiManager;

//  Black Pill starts execution at function main().
entry!(main);

// A quick type alias for the qei pins
type QeiPins = (
    bluepill_hal::gpio::gpiob::PB6<bluepill_hal::gpio::Input<bluepill_hal::gpio::Floating>>,
    bluepill_hal::gpio::gpiob::PB7<bluepill_hal::gpio::Input<bluepill_hal::gpio::Floating>>,
);

static mut QEIM: Option<QeiManager<Qei<bluepill_hal::stm32f103xx::TIM4, QeiPins>>> = None;

fn tim2_interrupt() {
    unsafe {
        // Clear interrupt pending flag;
        (*f103::TIM2::ptr()).sr.modify(|_, w| w.uif().clear_bit());
        // Take a sample
        QEIM.as_mut().unwrap().sample_unwrap();
    };
}

fn main() -> ! {
    let mut debug_out = hio::hstdout().unwrap();

    let bluepill = Peripherals::take().unwrap();
    let cortex = CortexPeripherals::take().unwrap();

    let mut nvic = cortex.NVIC;
    let mut rcc = bluepill.RCC.constrain();
    let mut flash = bluepill.FLASH.constrain();
    let mut afio = bluepill.AFIO.constrain(&mut rcc.apb2);

    // Configure the clock tree
    let clocks = rcc.cfgr.freeze(&mut flash.acr);

    // Initialize the GPIO pins
    let gpiob = bluepill.GPIOB.split(&mut rcc.apb2);
    let pb6 = gpiob.pb6;
    let pb7 = gpiob.pb7;

    // Use tim2 to sample at 1kHz the qei counter
    let mut tim2 =
        bluepill_hal::timer::Timer::tim2(bluepill.TIM2, 1000.hz(), clocks, &mut rcc.apb1);

    // Set up tim4 on pb6 and pb7 to be in encoder mode
    let qei = Qei::tim4(bluepill.TIM4, (pb6, pb7), &mut afio.mapr, &mut rcc.apb1);
    unsafe {
        QEIM = Some(QeiManager::new(qei));
    }

    // Enable the interrupts for tim2
    nvic.enable(Interrupt::TIM2);
    tim2.listen(bluepill_hal::timer::Event::Update);

    loop {
        // Print using hstdio the qei value 
        writeln!(
            debug_out,
            "Count : {}",
            unsafe { QEIM.as_mut().unwrap().count()},
        )
        .unwrap();
       
    }
}

// Declare the tim2 interrupt
interrupt!(TIM2, tim2_interrupt);

//  For any hard faults, show a message on the debug console and stop.
exception!(HardFault, hard_fault);

fn hard_fault(ef: &ExceptionFrame) -> ! {
    panic!("Hard fault: {:#?}", ef);
}

//  For any unhandled interrupts, show a message on the debug console and stop.
exception!(*, default_handler);

fn default_handler(irqn: i16) {
    panic!("Unhandled exception (IRQn = {})", irqn);
}