diff options
-rw-r--r-- | ble/src/main.rs | 53 | ||||
-rw-r--r-- | ble/src/uarte1.rs | 85 |
2 files changed, 131 insertions, 7 deletions
diff --git a/ble/src/main.rs b/ble/src/main.rs index 2da6de9..3c98b7e 100644 --- a/ble/src/main.rs +++ b/ble/src/main.rs @@ -7,13 +7,13 @@ mod i2c; mod logger; mod macros; mod rtc; +mod uarte1; 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}; +use log::{info, LevelFilter}; #[allow(unused_imports)] extern crate panic_semihosting; @@ -33,7 +33,6 @@ 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. @@ -53,7 +52,7 @@ fn main() -> ! { 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( + let (mut twis_reader, mut twis_handler) = i2c::setup(Twis::new( I2C_ADDR, nrf52.TWIS0, twis::Pins { @@ -68,27 +67,62 @@ fn main() -> ! { .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); + let uarte1 = uarte1(nrf52.UARTE1, txp, rxp); + let (mut uarte1_reader, mut uarte1_handler) = uarte1::setup(uarte1); 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); + hs.register(2, &mut uarte1_handler); + nvic.enable(Interrupt::UARTE1); info!("Bootstrap complete."); let mut last_tick = rtc::millis(); last_tick -= last_tick % 1024; + let mut buf: [u8; 256] = [0; 256]; loop { let tick = rtc::millis(); if tick >= last_tick + 1024 { last_tick = tick; last_tick -= last_tick % 1024; - trace!("."); - write!(uarte1, "!").expect("uarte1 write"); } + if !twis_reader.is_empty() { + let mut i = 0; + for b in &mut twis_reader { + if i == buf.len() { + info!("i²c data: {:?}", &buf[0..i]); + i = 0; + } + buf[i] = b; + i += 1; + } + info!("i²c data: {:?}", &buf[0..i]); + } + + if !uarte1_reader.is_empty() { + let mut i = 0; + for b in &mut uarte1_reader { + if i == buf.len() { + info!( + "serial - {}: {}", + i, + core::str::from_utf8(&buf[0..i]).expect("utf8conv") + ); + i = 0; + } + buf[i] = b; + i += 1; + } + info!( + "serial - {}: {}", + i, + core::str::from_utf8(&buf[0..i]).expect("utf8conv") + ); + } wfi(); } }); @@ -132,3 +166,8 @@ fn RTC0() { fn SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0() { HANDLERS.call(1); } + +#[interrupt] +fn UARTE1() { + HANDLERS.call(2); +} diff --git a/ble/src/uarte1.rs b/ble/src/uarte1.rs new file mode 100644 index 0000000..61d631e --- /dev/null +++ b/ble/src/uarte1.rs @@ -0,0 +1,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"); + } +} |