diff --git a/Cargo.lock b/Cargo.lock index 582faf5..8153ae3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,10 +3,16 @@ version = 4 [[package]] -name = "az" -version = "1.3.0" +name = "autocfg" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5eb007b7cacc6c660343e96f650fedf4b5a77512399eb952ca6642cf8d13f7" +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" + +[[package]] +name = "az" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" [[package]] name = "bare-metal" @@ -61,6 +67,7 @@ checksum = "8ec610d8f49840a5b376c69663b6369e71f4b34484b9b2eb29fb918d92516cb9" dependencies = [ "bare-metal", "bitfield", + "critical-section", "embedded-hal 0.2.7", "volatile-register", ] @@ -91,6 +98,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" +[[package]] +name = "critical-section-lock-mut" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbb9762738c1ef9d31b7586c00c0158d20025a734f9f6905282c1fc5a2e182f0" +dependencies = [ + "critical-section", +] + [[package]] name = "crunchy" version = "0.2.4" @@ -106,6 +122,29 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "embedded-graphics" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e8da660bb0c829b34a56a965490597f82a55e767b91f9543be80ce8ccb416fe" +dependencies = [ + "az", + "byteorder", + "embedded-graphics-core", + "float-cmp", + "micromath", +] + +[[package]] +name = "embedded-graphics-core" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95743bef3ff70fcba3930246c4e6872882bbea0dcc6da2ca860112e0cd4bd09f" +dependencies = [ + "az", + "byteorder", +] + [[package]] name = "embedded-hal" version = "0.2.7" @@ -122,6 +161,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "361a90feb7004eca4019fb28352a9465666b24f840f5c3cddf0ff13920590b89" +[[package]] +name = "embedded-hal-bus" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "513e0b3a8fb7d3013a8ae17a834283f170deaf7d0eeab0a7c1a36ad4dd356d22" +dependencies = [ + "critical-section", + "embedded-hal 1.0.0", +] + [[package]] name = "embedded-io" version = "0.7.1" @@ -136,9 +185,9 @@ checksum = "a21dea9854beb860f3062d10228ce9b976da520a73474aed3171ec276bc0c032" [[package]] name = "fixed" -version = "1.31.0" +version = "1.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9af2cbf772fa6d1c11358f92ef554cb6b386201210bcf0e91fb7fba8a907fb40" +checksum = "707070ccf8c4173548210893a0186e29c266901b71ed20cd9e2ca0193dfe95c3" dependencies = [ "az", "bytemuck", @@ -146,6 +195,15 @@ dependencies = [ "typenum", ] +[[package]] +name = "float-cmp" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +dependencies = [ + "num-traits", +] + [[package]] name = "half" version = "2.7.1" @@ -253,13 +311,21 @@ version = "0.1.0" dependencies = [ "cortex-m", "cortex-m-rt", + "critical-section", + "critical-section-lock-mut", + "embedded-graphics", "embedded-hal 1.0.0", + "embedded-hal-bus", "embedded-io", "heapless 0.9.3", "libm", "lsm303agr", "microbit-v2", + "mipidsi", + "nrf52833-hal", "panic-halt", + "panic-rtt-target", + "rtt-target", ] [[package]] @@ -282,6 +348,23 @@ dependencies = [ "microbit-common", ] +[[package]] +name = "micromath" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c8dda44ff03a2f238717214da50f65d5a53b45cd213a7370424ffdb6fae815" + +[[package]] +name = "mipidsi" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "790ebd28bd67addbccf41b1c0c188c26bb9f5bdcd91d4d6da9bd558e20d97a1d" +dependencies = [ + "embedded-graphics-core", + "embedded-hal 1.0.0", + "heapless 0.8.0", +] + [[package]] name = "nb" version = "0.1.3" @@ -307,6 +390,7 @@ dependencies = [ "cfg-if", "cortex-m", "embedded-dma", + "embedded-hal 0.2.7", "embedded-hal 1.0.0", "embedded-io", "embedded-storage", @@ -351,12 +435,32 @@ dependencies = [ "vcell", ] +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "panic-halt" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a513e167849a384b7f9b746e517604398518590a9142f4846a32e3c2a4de7b11" +[[package]] +name = "panic-rtt-target" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8116ffce1f89818647b84fba66d16cfdf3c0bee3c9320e606588d3e7415ce7" +dependencies = [ + "critical-section", + "portable-atomic", + "rtt-target", +] + [[package]] name = "portable-atomic" version = "1.13.1" @@ -409,6 +513,17 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76afc826de14238e6e8c374ddcc1fa19e374fd8dd986b0d2af0d02377261d83c" +[[package]] +name = "rtt-target" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7afed1f4302eeba88c601636cf2c554c45e1cbb464bab44c6012bab0e71473c" +dependencies = [ + "critical-section", + "portable-atomic", + "ufmt-write", +] + [[package]] name = "rustc_version" version = "0.2.3" @@ -479,6 +594,12 @@ version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40ce102ab67701b8526c123c1bab5cbe42d7040ccfd0f64af1a385808d2f43de" +[[package]] +name = "ufmt-write" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e87a2ed6b42ec5e28cc3b94c09982969e9227600b2e3dcbc1db927a84c06bd69" + [[package]] name = "unicase" version = "2.9.0" diff --git a/Cargo.toml b/Cargo.toml index 4686acc..d736b9a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,8 +8,16 @@ cortex-m-rt = "0.7.5" microbit-v2 = "0.16.0" embedded-hal = "1.0.0" panic-halt = "1.0.0" -cortex-m = "0.7.7" +cortex-m = { version = "0.7.7", features = ["critical-section-single-core"] } embedded-io = "0.7.1" heapless = "0.9.3" lsm303agr = "1.1.0" libm = "0.2.16" +panic-rtt-target = "0.2.0" +rtt-target = "0.6.2" +critical-section = "1.2.0" +critical-section-lock-mut = "0.1.2" +nrf52833-hal = "0.19.0" +mipidsi = "0.10.0" +embedded-graphics = "0.8.2" +embedded-hal-bus = "0.3.0" diff --git a/src/bin/analog.rs b/src/bin/analog.rs new file mode 100644 index 0000000..6dabc47 --- /dev/null +++ b/src/bin/analog.rs @@ -0,0 +1,60 @@ +#![no_main] +#![no_std] + +use cortex_m_rt::entry; +use embedded_hal::delay::DelayNs; +use microbit::{Board, adc::Default}; +use nrf52833_hal::{Saadc, Timer, saadc::SaadcConfig}; +use panic_rtt_target as _; +use rtt_target::{rprintln, rtt_init_print}; + +const THRESHOLD: i16 = 16; + +const LEFT_VALUE: i16 = -1; +const LEFT_NAME: &str = "LEFT"; + +const UP_VALUE: i16 = 117; +const UP_NAME: &str = "UP"; + +const DOWN_VALUE: i16 = 269; +const DOWN_NAME: &str = "DOWN"; + +const RIGHT_VALUE: i16 = 413; +const RIGHT_NAME: &str = "RIGHT"; + +const SEL_VALUE: i16 = 609; +const SEL_NAME: &str = "SELECT"; + +const NO_VALUE: i16 = 845; +const NO_NAME: &str = "NO"; + +#[entry] +fn main() -> ! { + rtt_init_print!(); + let board = Board::take().unwrap(); + let mut timer = Timer::new(board.TIMER0); + + let saadc_config = SaadcConfig::default_10bit(); + let mut saadc = Saadc::new(board.ADC, saadc_config); + let mut saadc_pin = board.edge.e00; + + loop { + if let Ok(value) = saadc.read_channel(&mut saadc_pin) { + rprintln!("value is {}", value); + + for (test, name) in [ + ( LEFT_VALUE, LEFT_NAME ), + ( UP_VALUE, UP_NAME ), + ( DOWN_VALUE, DOWN_NAME ), + ( RIGHT_VALUE, RIGHT_NAME ), + ( SEL_VALUE, SEL_NAME ), + ( NO_VALUE, NO_NAME ), + ] { + if value > test - THRESHOLD && value < test + THRESHOLD { + rprintln!("detected {}", name); + } + } + } + timer.delay_ms(1000); + } +} diff --git a/src/bin/compass.rs b/src/bin/compass.rs new file mode 100644 index 0000000..935a501 --- /dev/null +++ b/src/bin/compass.rs @@ -0,0 +1,75 @@ +#![no_main] +#![no_std] + +use core::f32::consts::PI; + +use cortex_m_rt::entry; +use embedded_hal::delay::DelayNs; +use libm::{atan2f, floorf}; +use lsm303agr::{Lsm303agr, MagMode, MagOutputDataRate}; +use microbit::{display::blocking::Display, hal::{Timer, Twim}, pac::twim0::frequency::FREQUENCY_A}; +use panic_halt as _; + +mod calibration { + type Vec = (i32, i32, i32); + + const CAL_CENTER: Vec = (-12892, 21810, -1080); + const CAL_SCALE: Vec = (1066, 1049, 1072); + + pub fn calibrate(v: Vec) -> Vec { + let mut out = (-v.1, -v.0, v.2); + out.0 = ((out.0 - CAL_CENTER.0) * CAL_SCALE.0) >> 10; + out.1 = ((out.1 - CAL_CENTER.1) * CAL_SCALE.1) >> 10; + out.2 = ((out.2 - CAL_CENTER.2) * CAL_SCALE.2) >> 10; + (-out.1, out.0, out.2) + } +} + +#[entry] +fn main() -> ! { + let board = microbit::Board::take().unwrap(); + + let i2c = Twim::new(board.TWIM0, board.i2c_internal.into(), FREQUENCY_A::K100); + let mut timer = Timer::new(board.TIMER0); + let mut display = Display::new(board.display_pins); + + let mut sensor = Lsm303agr::new_with_i2c(i2c); + sensor.init().unwrap(); + sensor.set_mag_mode_and_odr(&mut timer, MagMode::HighResolution, MagOutputDataRate::Hz10).unwrap(); + let mut sensor = sensor.into_mag_continuous().ok().unwrap(); + + let mut leds = [[0u8; 5]; 5]; + + let indices = [ + (2, 0) /* W */, (3, 0) /* W-SW */, (4, 0) /* SW */, (4, 1) /* S-SW */, + (4, 2) /* S */, (4, 3) /* S-SE */, (4, 4) /* SE */, (3, 4) /* E-SE */, + (2, 4) /* E */, (1, 4) /* E-NE */, (0, 4) /* NE */, (0, 3) /* N-NE */, + (0, 2) /* N */, (0, 1) /* N-NW */, (0, 0) /* NW */, (1, 0) /* W-NW */, + ]; + + loop { + while !sensor.mag_status().unwrap().xyz_new_data() { + timer.delay_ms(1u32); + } + + let (x, y, _) = calibration::calibrate(sensor.magnetic_field().unwrap().xyz_nt()); + //let (x, y, _) = sensor.magnetic_field().unwrap().xyz_nt(); + + let theta = atan2f(y as f32, x as f32); + + let seg = floorf(16.0 * theta / PI) as i8; + + let index = if seg >= 15 || seg <= -15 { + 8 + } else if seg >= 0 { + (seg / 2) as usize + } else { + ((31 + seg) / 2) as usize + }; + let (r, c) = indices[index]; + leds[r][c] = 255u8; + display.show(&mut timer, leds, 100); + leds[r][c] = 0u8; + display.clear(); + } +} diff --git a/src/bin/display.rs b/src/bin/display.rs new file mode 100644 index 0000000..ea1992b --- /dev/null +++ b/src/bin/display.rs @@ -0,0 +1,64 @@ +#![no_main] +#![no_std] + +use cortex_m_rt::entry; +use embedded_graphics::{pixelcolor::Rgb565, prelude::{DrawTarget, Point, WebColors}, primitives::Rectangle}; +use embedded_hal::digital::OutputPin; +use embedded_hal_bus::spi::ExclusiveDevice; +use microbit::Board; +use mipidsi::{Builder, interface::SpiInterface, models, options::ColorInversion}; +use nrf52833_hal::{Timer, gpio::Level, spi::{self, Spi}, spim}; +use panic_rtt_target as _; +use rtt_target::{rprintln, rtt_init_print}; + +#[entry] +fn main() -> ! { + rtt_init_print!(); + let board = Board::take().unwrap(); + + let mut timer0 = Timer::new(board.TIMER0); + let mut timer1 = Timer::new(board.TIMER1); + + board.pins.p0_01.into_push_pull_output(Level::Low).set_high(); + + let spi_pins = spi::Pins { + sck: Some(board.pins.p0_17.into_push_pull_output(Level::Low).degrade()), + mosi: Some(board.pins.p0_13.into_push_pull_output(Level::Low).degrade()), + miso: None, + }; + + let bus = Spi::new(board.SPI0, spi_pins, spi::Frequency::M8, spim::MODE_3); + let spi = ExclusiveDevice::new( + bus, + board.edge.e16.into_push_pull_output(Level::Low), + &mut timer0, + ).unwrap(); + + let mut buffer = [0u8; 512]; + + let interface = SpiInterface::new( + spi, + board.edge.e08.into_push_pull_output(Level::Low), + &mut buffer, + ); + + let mut display = Builder::new(models::ST7789, interface) + .display_size(240, 320) + .invert_colors(ColorInversion::Inverted) + .init(&mut timer1).unwrap(); + + display.clear(Rgb565::CSS_GREEN).unwrap(); + display.fill_solid( + &Rectangle::with_corners( + Point::new(100, 100), + Point::new(150, 150), + ), + Rgb565::CSS_ROYAL_BLUE, + ).unwrap(); + + rprintln!("Should be done here"); + + loop { + continue; + } +} diff --git a/src/bin/interrupt.rs b/src/bin/interrupt.rs new file mode 100644 index 0000000..6314357 --- /dev/null +++ b/src/bin/interrupt.rs @@ -0,0 +1,63 @@ +#![no_main] +#![no_std] + +use core::sync::atomic::AtomicUsize; + +use cortex_m::asm; +use cortex_m_rt::entry; +use critical_section_lock_mut::LockMut; +use microbit::{Board, hal::{Timer, gpiote::Gpiote}, pac::{self, interrupt}}; +use panic_rtt_target as _; +use rtt_target::{rprintln, rtt_init_print}; + +static COUNTER: AtomicUsize = AtomicUsize::new(0); +static GPIOTE_PERIPHERAL: LockMut = LockMut::new(); +static DEBOUNCE_TIMER: LockMut> = LockMut::new(); + +const DEBOUNCE_TIME: u32 = 100 * 1_000_000 / 1000; + +#[interrupt] +fn GPIOTE() { + DEBOUNCE_TIMER.with_lock(|t| { + if t.read() == 0 { + let _ = COUNTER.fetch_add(1, core::sync::atomic::Ordering::AcqRel); + t.start(DEBOUNCE_TIME); + } + }); + GPIOTE_PERIPHERAL.with_lock(|g| { + g.channel0().reset_events(); + }); +} + +#[entry] +fn main() -> ! { + rtt_init_print!(); + let board = Board::take().unwrap(); + let button_a = board.buttons.button_a.into_floating_input(); + + let gpiote = Gpiote::new(board.GPIOTE); + let channel = gpiote.channel0(); + channel.input_pin(&button_a.degrade()) + .hi_to_lo() + .enable_interrupt(); + channel.reset_events(); + GPIOTE_PERIPHERAL.init(gpiote); + + let mut timer = Timer::new(board.TIMER0); + timer.disable_interrupt(); + timer.reset_event(); + DEBOUNCE_TIMER.init(timer); + + unsafe { pac::NVIC::unmask(pac::Interrupt::GPIOTE) }; + pac::NVIC::unpend(pac::Interrupt::GPIOTE); + + let mut cur_count = 0; + loop { + asm::wfi(); + let count = COUNTER.load(core::sync::atomic::Ordering::Acquire); + if count > cur_count { + rprintln!("ouch {}", count); + cur_count = count; + } + } +}