summaryrefslogtreecommitdiffstats
path: root/ble/src/main.rs
blob: 2da6de9ba91d170a098271e9cb015a8191a0ec78 (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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
//! BLE interface.

#![no_std]
#![no_main]

mod i2c;
mod logger;
mod macros;
mod rtc;

use clint::HandlerArray;
use core::fmt::Write;
use core::mem;
use cortex_m::asm::wfi;
use cortex_m_rt::{entry, exception, ExceptionFrame};
use log::{info, trace, LevelFilter};

#[allow(unused_imports)]
extern crate panic_semihosting;

use nrf52840_mdk_bsp::{
    hal::{
        gpio::{Floating, Input, Level, Output, Pin, PushPull},
        target::{interrupt, Interrupt, UARTE0},
        twis::{self, Twis},
        uarte::{self, Baudrate as UartBaudrate, Parity as UartParity, Uarte},
        Clocks, Rtc,
    },
    Board,
};

const I2C_ADDR: u8 = 4;

// TODO:
//   * set up serial reader for trinket
//   * set up i²c interface for keyboard reports
//   * and, finally, bluetooth

// Interrupt handler table.
static HANDLERS: HandlerArray = HandlerArray::new();

#[entry]
fn main() -> ! {
    let nrf52 = Board::take().unwrap();

    let uart_wrapped = logger::WriteWrapper::new(nrf52.cdc);
    let logger = logger::SerialLogger::new(uart_wrapped);
    let logger_ref: &'static logger::SerialLogger<UARTE0> = unsafe { mem::transmute(&logger) };
    log::set_logger(logger_ref).expect("setting logger");
    log::set_max_level(LevelFilter::Trace);

    nrf52.RTC0.intenset.write(|w| w.tick().set());

    let mut nvic = nrf52.NVIC;
    let mut rtc_handler = rtc::setup(Rtc::new(nrf52.RTC0), Clocks::new(nrf52.CLOCK));
    let mut twis_handler = i2c::setup(Twis::new(
        I2C_ADDR,
        nrf52.TWIS0,
        twis::Pins {
            scl: nrf52.pins.P0_06.into_floating_input().degrade(),
            sda: nrf52.pins.P0_07.into_floating_input().degrade(),
        },
    ));

    let txp = nrf52
        .pins
        .P0_26
        .into_push_pull_output(Level::High)
        .degrade();
    let rxp = nrf52.pins.P0_25.into_floating_input().degrade();
    let mut uarte1 = uarte1(nrf52.UARTE1, txp, rxp);

    HANDLERS.with_overrides(|hs| {
        hs.register(0, &mut rtc_handler);
        nvic.enable(Interrupt::RTC0);
        hs.register(1, &mut twis_handler);
        nvic.enable(Interrupt::SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0);

        info!("Bootstrap complete.");

        let mut last_tick = rtc::millis();
        last_tick -= last_tick % 1024;
        loop {
            let tick = rtc::millis();
            if tick >= last_tick + 1024 {
                last_tick = tick;
                last_tick -= last_tick % 1024;
                trace!(".");
                write!(uarte1, "!").expect("uarte1 write");
            }

            wfi();
        }
    });
    unreachable!();
}

fn uarte1<U>(uarte: U, tx: Pin<Output<PushPull>>, rx: Pin<Input<Floating>>) -> Uarte<U>
where
    U: uarte::Instance,
{
    Uarte::new(
        uarte,
        uarte::Pins {
            txd: tx,
            rxd: rx,
            cts: None,
            rts: None,
        },
        UartParity::EXCLUDED,
        UartBaudrate::BAUD115200,
    )
}

#[exception]
fn HardFault(ef: &ExceptionFrame) -> ! {
    log::logger().flush();
    logln_now!("!!! Hard Fault - ef: {:?} !!!", ef);
    logln_now!("flushing log");
    loop {
        log::logger().flush();
        wfi()
    }
}

#[interrupt]
fn RTC0() {
    HANDLERS.call(0);
}

#[interrupt]
fn SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0() {
    HANDLERS.call(1);
}