Firmware for the b-parasite board, but in Rust!
1#![feature(impl_trait_in_assoc_type)]
2#![no_std]
3#![no_main]
4
5mod adc;
6mod ble;
7mod button;
8mod constants;
9mod led;
10mod shtc3;
11mod state;
12mod timer;
13
14use embassy_executor::Executor;
15use sachy_fmt::{info, unwrap};
16
17use embassy_nrf::{
18 bind_interrupts,
19 gpio::{Input, Level, Output, OutputDrive},
20 peripherals,
21 rng::{self, Rng},
22 saadc, twim,
23};
24#[cfg(not(feature = "defmt"))]
25use panic_halt as _;
26use static_cell::StaticCell;
27#[cfg(feature = "defmt")]
28use {defmt_rtt as _, panic_probe as _};
29
30use nrf_sdc::mpsl::MultiprotocolServiceLayer;
31use nrf_sdc::{self as sdc, mpsl};
32
33bind_interrupts!(struct Irqs {
34 RNG => rng::InterruptHandler<peripherals::RNG>;
35 EGU0_SWI0 => nrf_sdc::mpsl::LowPrioInterruptHandler;
36 CLOCK_POWER => nrf_sdc::mpsl::ClockInterruptHandler;
37 RADIO => nrf_sdc::mpsl::HighPrioInterruptHandler;
38 TIMER0 => nrf_sdc::mpsl::HighPrioInterruptHandler;
39 RTC0 => nrf_sdc::mpsl::HighPrioInterruptHandler;
40 TWISPI0 => twim::InterruptHandler<peripherals::TWISPI0>;
41 SAADC => saadc::InterruptHandler;
42});
43
44#[cortex_m_rt::entry]
45fn main() -> ! {
46 let p = embassy_nrf::init(Default::default());
47
48 let photo_ctrl = Output::new(p.P0_29, Level::Low, OutputDrive::Standard);
49
50 let mpsl_p =
51 mpsl::Peripherals::new(p.RTC0, p.TIMER0, p.TEMP, p.PPI_CH19, p.PPI_CH30, p.PPI_CH31);
52 let lfclk_cfg = mpsl::raw::mpsl_clock_lfclk_cfg_t {
53 source: mpsl::raw::MPSL_CLOCK_LF_SRC_RC as u8,
54 rc_ctiv: mpsl::raw::MPSL_RECOMMENDED_RC_CTIV as u8,
55 rc_temp_ctiv: mpsl::raw::MPSL_RECOMMENDED_RC_TEMP_CTIV as u8,
56 accuracy_ppm: mpsl::raw::MPSL_DEFAULT_CLOCK_ACCURACY_PPM as u16,
57 skip_wait_lfclk_started: mpsl::raw::MPSL_DEFAULT_SKIP_WAIT_LFCLK_STARTED != 0,
58 };
59 static MPSL: StaticCell<MultiprotocolServiceLayer> = StaticCell::new();
60 let mpsl = MPSL.init(unwrap!(mpsl::MultiprotocolServiceLayer::new(
61 mpsl_p, Irqs, lfclk_cfg
62 )));
63 let sdc_p = sdc::Peripherals::new(
64 p.PPI_CH17, p.PPI_CH18, p.PPI_CH20, p.PPI_CH21, p.PPI_CH22, p.PPI_CH23, p.PPI_CH24,
65 p.PPI_CH25, p.PPI_CH26, p.PPI_CH27, p.PPI_CH28, p.PPI_CH29,
66 );
67
68 static DEVICE_RNG: StaticCell<Rng<'static, embassy_nrf::mode::Async>> = StaticCell::new();
69 let rng = DEVICE_RNG.init_with(|| rng::Rng::new(p.RNG, Irqs));
70
71 static SDC_MEM: StaticCell<sdc::Mem<792>> = StaticCell::new();
72 let sdc_mem = SDC_MEM.init_with(sdc::Mem::new);
73
74 let sdc = unwrap!(ble::build_sdc(sdc_p, rng, mpsl, sdc_mem));
75
76 static EXECUTOR: StaticCell<Executor> = StaticCell::new();
77
78 EXECUTOR.init_with(Executor::new).run(|spawner| {
79 spawner.must_spawn(button::task(Input::new(
80 p.P0_30,
81 embassy_nrf::gpio::Pull::Up,
82 )));
83 spawner.must_spawn(led::task(Output::new(
84 p.P0_28,
85 Level::Low,
86 OutputDrive::Standard,
87 )));
88 spawner.must_spawn(shtc3::task(p.TWISPI0, p.P0_24, p.P0_13));
89 spawner.must_spawn(adc::task(
90 p.SAADC, p.P0_02, p.P0_03, photo_ctrl, p.PWM0, p.P0_05,
91 ));
92 spawner.must_spawn(timer::task());
93 spawner.must_spawn(ble::mpsl_task(&*mpsl));
94 spawner.must_spawn(ble::run(sdc));
95
96 info!("Sachy's Parasite is go!");
97 })
98}