//! Serial interface echo server
//!
//! In this example every received byte will be sent back to the sender. You can test this example
//! with serial terminal emulator like `minicom`.
//!
//!
#![deny(unsafe_code)]
//#![deny(warnings)]
#![feature(proc_macro)]
#![no_std]

#[macro_use(singleton)]
extern crate cortex_m;
extern crate cortex_m_rtfm as rtfm;
extern crate stm32f4x_hal as hal;

use hal::prelude::*;
use hal::serial::{Rx, Serial, Tx};
use hal::dma::Event;
use hal::stm32f4x;
use rtfm::{app, Threshold};
use cortex_m::asm;

app! {
    device: stm32f4x,

    resources : {
        static X: u32;
    //    static CB: CircBuffer<[u8; 8], dma1::S6<C5>>;
    },

    tasks: {
        DMA1_STREAM6: {
            path: tx,
            resources : [X]
        },
        DMA1_STREAM5: {
            path: rx,
            resources : [X]
        }
    }
}

fn init(p: init::Peripherals) -> init::LateResources {
    let mut flash = p.device.FLASH.constrain();
    let mut rcc = p.device.RCC.constrain();
    let mut gpioa = p.device.GPIOA.split(&mut rcc.ahb1);
    let streams = p.device.DMA1.split(&mut rcc.ahb1);
    let mut tx_stream = streams.1.into_channel4(); // S6<C4>
    let mut rx_stream = streams.0.into_channel4(); // S5<C4>

    let clocks = rcc.cfgr.freeze(&mut flash.acr);

    let tx = gpioa.pa2.into_af7(&mut gpioa.moder, &mut gpioa.afrl);
    let rx = gpioa.pa3.into_af7(&mut gpioa.moder, &mut gpioa.afrl);

    let mut serial = Serial::usart2(
        p.device.USART2,
        (tx, rx),
        115_200.bps(),
        clocks,
        &mut rcc.apb1,
    );

    let (tx, rx) = serial.split();
    //tx_stream.listen(Event::TransferComplete);
    rx_stream.listen(Event::TransferComplete);

    let buf = singleton!(: [u8; 8] = [0; 8]).unwrap();

    let _ = tx.write_all(tx_stream, b"The quick brown fox");
    init::LateResources { X: 0 }
}

fn idle() -> ! {
    // sleep
    loop {
        // rtfm::wfi();
    }
}

fn tx(_: &mut Threshold, mut r: DMA1_STREAM6::Resources) {
    asm::bkpt();
}

fn rx(_: &mut Threshold, mut r: DMA1_STREAM5::Resources) {
    asm::bkpt();
}