aboutsummaryrefslogtreecommitdiffstats
path: root/src/bin
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/example/display.rs89
-rw-r--r--src/bin/example/main.rs89
-rw-r--r--src/bin/example/radio.rs70
3 files changed, 248 insertions, 0 deletions
diff --git a/src/bin/example/display.rs b/src/bin/example/display.rs
new file mode 100644
index 0000000..5830254
--- /dev/null
+++ b/src/bin/example/display.rs
@@ -0,0 +1,89 @@
+use defmt::info;
+use display_interface_spi::SpiInterface;
+use embassy_nrf::gpio::{AnyPin, Level, Output, OutputDrive};
+use embassy_nrf::{interrupt::typelevel::Binding, spim, Peri};
+use embassy_time::Timer;
+use embedded_graphics::{
+ framebuffer::{buffer_size, Framebuffer},
+ pixelcolor::{raw::LittleEndian, Gray4},
+};
+use embedded_hal_bus::spi::ExclusiveDevice;
+use ssd1322::{DisplayAsync, PixelCoord};
+
+type SPIDevice<'t> = ExclusiveDevice<spim::Spim<'t>, Output<'t>, embassy_time::Delay>;
+
+type Display<'t> = DisplayAsync<SpiInterface<SPIDevice<'t>, Output<'t>>>;
+
+pub struct Pins<'t> {
+ pub ven: Peri<'t, AnyPin>,
+ pub rst: Peri<'t, AnyPin>,
+ pub sck: Peri<'t, AnyPin>,
+ pub sdo: Peri<'t, AnyPin>,
+ pub cs: Peri<'t, AnyPin>,
+ pub dc: Peri<'t, AnyPin>,
+}
+
+pub async fn init<T: spim::Instance>(
+ spi_instance: Peri<'static, T>,
+ irq_binding: impl Binding<T::Interrupt, spim::InterruptHandler<T>> + 'static,
+ pins: Pins<'static>,
+) -> Display<'static> {
+ Output::new(pins.ven, Level::High, OutputDrive::Standard).persist();
+
+ let mut out_rst = Output::new(pins.rst, Level::Low, OutputDrive::Standard);
+ Timer::after_millis(2).await;
+ out_rst.set_high();
+ Timer::after_millis(2).await;
+
+ let out_cs = Output::new(pins.cs, Level::High, OutputDrive::Standard);
+ let out_dc = Output::new(pins.dc, Level::High, OutputDrive::Standard);
+
+ let mut spi_config = spim::Config::default();
+ spi_config.frequency = spim::Frequency::M8;
+ let spi_bus = spim::Spim::new_txonly(spi_instance, irq_binding, pins.sck, pins.sdo, spi_config);
+ let spi_dev = ExclusiveDevice::new(spi_bus, out_cs, embassy_time::Delay).unwrap();
+ let spi_iface = SpiInterface::new(spi_dev, out_dc);
+
+ let mut display = DisplayAsync::new(spi_iface, PixelCoord(256, 64), PixelCoord(0x1C * 4, 0));
+
+ info!("initializing display");
+ display
+ .init(
+ ssd1322::ConfigAsync::new(
+ ssd1322::ComScanDirection::RowZeroLast,
+ ssd1322::ComLayout::Progressive,
+ )
+ .column_remap(ssd1322::command::ColumnRemap::Reverse)
+ .clock_fosc_divset(9, 1)
+ .display_enhancements(true, true)
+ .contrast_current(0x7f)
+ .phase_lengths(5, 15)
+ .precharge_voltage(0x1f)
+ .com_deselect_voltage(0x04),
+ )
+ .await
+ .unwrap();
+
+ display
+}
+
+#[embassy_executor::task]
+pub async fn task(mut display: Display<'static>) {
+ let mut fb =
+ Framebuffer::<Gray4, _, LittleEndian, 128, 64, { buffer_size::<Gray4>(128, 64) }>::new();
+
+ info!("display task starting");
+ t114_meshcore_example::display_task(&mut fb, async |fb| {
+ display
+ .region(PixelCoord(0, 0), PixelCoord(256, 64))
+ .unwrap()
+ .draw_packed(fb.data().iter().flat_map(|n| {
+ let upper = n & 0xf0;
+ let lower = n & 0x0f;
+ [upper | (upper >> 4), lower | (lower << 4)]
+ }))
+ .await
+ .unwrap();
+ })
+ .await;
+}
diff --git a/src/bin/example/main.rs b/src/bin/example/main.rs
new file mode 100644
index 0000000..94a8c9e
--- /dev/null
+++ b/src/bin/example/main.rs
@@ -0,0 +1,89 @@
+#![no_std]
+#![no_main]
+
+use alloc::boxed::Box;
+use embassy_executor::Spawner;
+use embassy_nrf::gpio::{Level, Output, OutputDrive};
+use embassy_nrf::{bind_interrupts, peripherals, spim};
+use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, mutex::Mutex};
+use embedded_alloc::LlffHeap as Heap;
+
+use {defmt_rtt as _, panic_probe as _};
+
+extern crate alloc;
+
+#[cfg(feature = "display")]
+mod display;
+
+mod radio;
+
+#[global_allocator]
+static HEAP: Heap = Heap::empty();
+
+bind_interrupts!(struct Irqs {
+ SPIM3 => spim::InterruptHandler<peripherals::SPI3>;
+ SPI2 => spim::InterruptHandler<peripherals::SPI2>;
+});
+
+type PinMutex<'a> = Mutex<CriticalSectionRawMutex, Output<'a>>;
+
+#[embassy_executor::task]
+async fn led_task(led_pin: &'static PinMutex<'static>) {
+ t114_meshcore_example::led_task(led_pin).await;
+}
+
+#[embassy_executor::main]
+async fn main(spawner: Spawner) {
+ {
+ use core::mem::MaybeUninit;
+ const HEAP_SIZE: usize = 64 * 1024;
+ static mut HEAP_MEM: [MaybeUninit<u8>; HEAP_SIZE] = [MaybeUninit::uninit(); HEAP_SIZE];
+ unsafe { HEAP.init(&raw mut HEAP_MEM as usize, HEAP_SIZE) }
+ }
+
+ let p = embassy_nrf::init(Default::default());
+
+ {
+ // led blink task
+ let led = Output::new(p.P1_03, Level::High, OutputDrive::Standard);
+ let pin: PinMutex = Mutex::new(led);
+ let pin_ref = Box::leak(Box::new(pin));
+ spawner.spawn(led_task(pin_ref)).unwrap();
+ }
+
+ #[cfg(feature = "display")]
+ {
+ let display = display::init(
+ p.SPI3,
+ Irqs,
+ display::Pins {
+ ven: p.P0_21.into(),
+ rst: p.P0_05.into(),
+ sck: p.P1_12.into(),
+ sdo: p.P1_14.into(),
+ cs: p.P1_15.into(),
+ dc: p.P1_13.into(),
+ },
+ )
+ .await;
+ spawner.spawn(display::task(display)).unwrap();
+ }
+
+ {
+ let radio = radio::init(
+ p.SPI2,
+ Irqs,
+ radio::Pins {
+ sck: p.P0_19.into(),
+ miso: p.P0_23.into(),
+ mosi: p.P0_22.into(),
+ cs: p.P0_24.into(),
+ rst: p.P0_25.into(),
+ dio1: p.P0_20.into(),
+ busy: p.P0_17.into(),
+ },
+ )
+ .await;
+ spawner.spawn(radio::task(radio)).unwrap();
+ }
+}
diff --git a/src/bin/example/radio.rs b/src/bin/example/radio.rs
new file mode 100644
index 0000000..db677ee
--- /dev/null
+++ b/src/bin/example/radio.rs
@@ -0,0 +1,70 @@
+use embassy_nrf::gpio::{AnyPin, Input, Level, Output, OutputDrive, Pull};
+use embassy_nrf::{interrupt::typelevel::Binding, spim, Peri};
+use embassy_time::Delay;
+use embedded_hal_bus::spi::ExclusiveDevice;
+
+use lora_phy::iv::GenericSx126xInterfaceVariant;
+use lora_phy::sx126x::{Config, Sx1262, Sx126x, TcxoCtrlVoltage};
+use lora_phy::LoRa;
+
+type SPIDevice<'t> = ExclusiveDevice<spim::Spim<'t>, Output<'t>, Delay>;
+
+type RadioImpl<'t> = LoRa<
+ Sx126x<SPIDevice<'t>, GenericSx126xInterfaceVariant<Output<'t>, Input<'t>>, Sx1262>,
+ Delay,
+>;
+
+pub struct Radio(RadioImpl<'static>);
+
+pub struct Pins<'t> {
+ pub sck: Peri<'t, AnyPin>,
+ pub miso: Peri<'t, AnyPin>,
+ pub mosi: Peri<'t, AnyPin>,
+ pub cs: Peri<'t, AnyPin>,
+ pub rst: Peri<'t, AnyPin>,
+ pub dio1: Peri<'t, AnyPin>,
+ pub busy: Peri<'t, AnyPin>,
+}
+
+pub async fn init<T: spim::Instance>(
+ spi_instance: Peri<'static, T>,
+ irq_binding: impl Binding<T::Interrupt, spim::InterruptHandler<T>> + 'static,
+ pins: Pins<'static>,
+) -> Radio {
+ let out_rst = Output::new(pins.rst, Level::High, OutputDrive::Standard);
+ let out_cs = Output::new(pins.cs, Level::High, OutputDrive::Standard);
+
+ let in_dio1 = Input::new(pins.dio1, Pull::None);
+ let in_busy = Input::new(pins.busy, Pull::None);
+
+ let mut spi_config = spim::Config::default();
+ spi_config.frequency = spim::Frequency::M8;
+ let spi_bus = spim::Spim::new(
+ spi_instance,
+ irq_binding,
+ pins.sck,
+ pins.miso,
+ pins.mosi,
+ spi_config,
+ );
+ let spi_dev = ExclusiveDevice::new(spi_bus, out_cs, Delay).unwrap();
+
+ let iv = GenericSx126xInterfaceVariant::new(out_rst, in_dio1, in_busy, None, None).unwrap();
+ let config = Config {
+ chip: Sx1262,
+ tcxo_ctrl: Some(TcxoCtrlVoltage::Ctrl1V8),
+ use_dcdc: true,
+ rx_boost: true,
+ };
+
+ let lora: RadioImpl = LoRa::new(Sx126x::new(spi_dev, iv, config), false, Delay)
+ .await
+ .unwrap();
+
+ Radio(lora)
+}
+
+#[embassy_executor::task]
+pub async fn task(mut radio: Radio) {
+ t114_meshcore_example::radio_task(&mut radio.0).await;
+}