A RPi Pico powered Lightning Detector
1#![feature(allocator_api)]
2#![allow(unexpected_cfgs)]
3#![no_std]
4#![no_main]
5
6mod allocator;
7mod detector;
8mod errors;
9mod locks;
10mod net;
11#[cfg(not(feature = "defmt"))]
12mod panic_handler;
13mod rpc;
14mod rtc;
15mod state;
16mod updates;
17mod utils;
18mod wifi;
19
20use crate::{allocator::PicoHeap, rtc::GlobalRtc};
21use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
22use embassy_executor::Executor;
23use embassy_rp::{
24 adc as rp_adc, bind_interrupts,
25 clocks::RoscRng,
26 gpio::{Level, Output},
27 multicore::{Stack, spawn_core1},
28 peripherals::PIO0,
29 pio::{InterruptHandler, Pio},
30 rtc::{self as rp_rtc, Rtc},
31};
32use sachy_fmt::*;
33use static_cell::{ConstStaticCell, StaticCell};
34
35extern crate alloc;
36
37#[cfg(feature = "defmt")]
38use {defmt_rtt as _, panic_probe as _};
39
40mod constants {
41 include!(concat!(env!("OUT_DIR"), "/constants.rs"));
42}
43
44use constants::HEAP_SIZE;
45
46#[global_allocator]
47static HEAP: PicoHeap<HEAP_SIZE> = PicoHeap::empty();
48
49bind_interrupts!(struct Irqs {
50 ADC_IRQ_FIFO => rp_adc::InterruptHandler;
51 PIO0_IRQ_0 => InterruptHandler<PIO0>;
52 RTC_IRQ => rp_rtc::InterruptHandler, rtc::GlobalRtcHandler;
53});
54
55#[unsafe(no_mangle)]
56unsafe extern "Rust" fn __getrandom_v03_custom(
57 dest: *mut u8,
58 len: usize,
59) -> Result<(), getrandom::Error> {
60 let slice = unsafe {
61 // Initialise the buffer with zeros before transmuting it into
62 // a mutable slice
63 core::ptr::write_bytes(dest, 0, len);
64 core::slice::from_raw_parts_mut(dest, len)
65 };
66
67 RoscRng.fill_bytes(slice);
68
69 Ok(())
70}
71
72#[cortex_m_rt::entry]
73fn main() -> ! {
74 let p = embassy_rp::init(Default::default());
75
76 info!("Welcome to Pico Strike!");
77 info!("Initialising Heap, SIZE: {}", HEAP_SIZE);
78 unwrap!(HEAP.init());
79
80 info!("Initialising drivers");
81 let pwm = embassy_strike_driver::drivers::rp::PwmDriver::new(p.PWM_SLICE5, p.PIN_27);
82 let adc = embassy_strike_driver::drivers::rp::AdcDriver::new(p.ADC, p.PIN_26, p.DMA_CH1, Irqs);
83
84 let pwr = Output::new(p.PIN_23, Level::Low);
85 let cs = Output::new(p.PIN_25, Level::High);
86 let mut pio = Pio::new(p.PIO0, Irqs);
87 let spi = PioSpi::new(
88 &mut pio.common,
89 pio.sm0,
90 DEFAULT_CLOCK_DIVIDER,
91 pio.irq0,
92 cs,
93 p.PIN_24,
94 p.PIN_29,
95 p.DMA_CH0,
96 );
97
98 info!("Initialising RTC");
99 let rtc = GlobalRtc::init(Rtc::new(p.RTC, Irqs));
100
101 static CORE1_STACK: ConstStaticCell<Stack<8192>> = ConstStaticCell::new(Stack::new());
102
103 info!("Initialising executors for multi-core tasks");
104 spawn_core1(p.CORE1, CORE1_STACK.take(), move || {
105 static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
106
107 EXECUTOR1.init_with(Executor::new).run(|spawner| {
108 info!("Spawning Detector task on Core 1");
109 spawner.must_spawn(detector::detector_task(adc, pwm, rtc));
110 })
111 });
112
113 static EXECUTOR0: StaticCell<Executor> = StaticCell::new();
114
115 EXECUTOR0.init_with(Executor::new).run(|spawner| {
116 info!("Spawning Network tasks on Core 0");
117 spawner.must_spawn(wifi::main_loop(spawner, rtc, spi, pwr));
118 });
119}