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