summaryrefslogtreecommitdiffstats
path: root/ble/src/uarte1.rs
blob: 61d631e7b50f5b9d02d1f8133ec90f4dd3942c0e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
use log::info;
use nrf52840_hal::uarte::{self, Uarte};
use starb::{Reader, RingBuffer, Writer};

static mut RB: RingBuffer<u8> = RingBuffer::new(0);

pub fn setup<I>(mut uarte: Uarte<I>) -> (Reader<'static, u8>, impl FnMut())
where
    I: uarte::Instance,
{
    uarte.0.intenset.write(|w| {
        w.endrx().set_bit();
        w.error().set_bit();
        w.rxto().set_bit();
        w.rxstarted().set_bit()
    });

    let mut buf: [u8; 255] = [0; 255];
    uarte
        .0
        .rxd
        .ptr
        .write(|w| unsafe { w.ptr().bits(buf.as_mut_ptr() as _) });
    uarte
        .0
        .rxd
        .maxcnt
        .write(|w| unsafe { w.maxcnt().bits(buf.len() as _) });
    uarte.0.tasks_startrx.write(|w| w.tasks_startrx().set_bit());
    let (rbr, mut rbw) = unsafe { RB.split() };

    // start rx into a buffer. it would be nice if we could do this
    // with rxrdy or something like i2c does.
    let cl = move || handler(&mut uarte, &mut rbw, &mut buf);
    (rbr, cl)
}

fn handler<I>(uarte: &mut Uarte<I>, writer: &mut Writer<u8>, buf: &mut [u8])
where
    I: uarte::Instance,
{
    if uarte.0.events_endrx.read().events_endrx().bit_is_set() {
        uarte.0.events_endrx.write(|w| w.events_endrx().clear_bit());

        // Copy DMA buffer to ring buffer.
        let len = uarte.0.rxd.amount.read().amount().bits();
        info!("endrx - {}", len);
        for i in 0..len {
            writer.unshift(buf[i as usize]).ok();
        }

        // Reset the DMA buffer. TODO: this is probably unneccesary.
        uarte
            .0
            .rxd
            .ptr
            .write(|w| unsafe { w.ptr().bits(buf.as_mut_ptr() as _) });
        uarte
            .0
            .rxd
            .maxcnt
            .write(|w| unsafe { w.maxcnt().bits(buf.len() as _) });

        // restart the read.
        uarte.0.tasks_startrx.write(|w| w.tasks_startrx().set_bit());
    } else if uarte.0.events_error.read().events_error().bit_is_set() {
        uarte.0.events_error.write(|w| w.events_error().clear_bit());
        info!("error: {:b}", uarte.0.errorsrc.read().bits());
    } else if uarte.0.events_rxto.read().events_rxto().bit_is_set() {
        uarte.0.events_rxto.write(|w| w.events_rxto().clear_bit());
        info!("rxto");
    } else if uarte
        .0
        .events_rxstarted
        .read()
        .events_rxstarted()
        .bit_is_set()
    {
        uarte
            .0
            .events_rxstarted
            .write(|w| w.events_rxstarted().clear_bit());
        info!("rxstarted");
    }
}