A RPi Pico powered Lightning Detector
1use embassy_strike_driver::{DetectorConfig, DetectorUpdate};
2use embassy_sync::channel::{Channel, Receiver, Sender};
3use sachy_fmt::info;
4use striker_proto::{StrikerResponse, Update};
5
6use crate::{
7 locks::DataTransferLock,
8 state::{DETECTOR_CONFIG, DETECTOR_CONFIG_UPDATES, DEVICE_STATE, DeviceState},
9};
10
11pub type NetDataChannel = Channel<DataTransferLock, StrikerResponse, 8>;
12pub type NetDataSender = Sender<'static, DataTransferLock, StrikerResponse, 8>;
13pub type NetDataReceiver = Receiver<'static, DataTransferLock, StrikerResponse, 8>;
14
15static NET_CHANNEL: NetDataChannel = Channel::new();
16
17pub struct UpdateConnection;
18
19impl UpdateConnection {
20 pub fn disconnect() {
21 DEVICE_STATE.lock(|state| state.set(DeviceState::Disconnected));
22 }
23
24 pub fn connect() {
25 DEVICE_STATE.lock(|state| state.set(DeviceState::Connected));
26 }
27
28 pub fn is_connected() -> bool {
29 DEVICE_STATE.lock(|state| state.get() == DeviceState::Connected)
30 }
31
32 pub fn get_receiver() -> NetDataReceiver {
33 NET_CHANNEL.receiver()
34 }
35
36 pub fn can_update() -> Option<NetDataSender> {
37 Self::is_connected().then(|| NET_CHANNEL.sender())
38 }
39
40 pub fn transmit_update(update: DetectorUpdate<'_>) {
41 let sender = Self::can_update();
42
43 match update {
44 DetectorUpdate::Tick { timestamp, level } => {
45 sender.and_then(|sender| {
46 sender
47 .try_send(StrikerResponse::Update(Update::Warning {
48 timestamp,
49 level,
50 }))
51 .ok()
52 });
53 }
54 DetectorUpdate::Detection {
55 timestamp,
56 average,
57 samples,
58 peaks,
59 } => {
60 info!("STRIKE @ {}: Peaks {}", timestamp, peaks);
61 sender.and_then(|sender| {
62 sender
63 .try_send(StrikerResponse::Update(Update::Strike {
64 timestamp,
65 peaks: peaks.to_vec(),
66 samples: samples
67 .iter()
68 .map(|&sample| (average as i16).saturating_sub_unsigned(sample))
69 .collect(),
70 average,
71 }))
72 .ok()
73 });
74 }
75 };
76 }
77}
78
79pub struct DetectorConfigUpdate {
80 pub blip_threshold: Option<u16>,
81 pub blip_size: Option<usize>,
82}
83
84pub struct DetectorConfigurationHandle;
85
86impl DetectorConfigurationHandle {
87 pub fn set_config(update: DetectorConfigUpdate) {
88 let update = DETECTOR_CONFIG.lock(|config| {
89 if let Some(size) = update.blip_size {
90 config.set_blip_size(size);
91 }
92
93 if let Some(threshold) = update.blip_threshold {
94 config.set_blip_threshold(threshold);
95 }
96
97 config.clone()
98 });
99 DETECTOR_CONFIG_UPDATES.signal(update);
100 }
101
102 pub fn get_config() -> DetectorConfig {
103 DETECTOR_CONFIG.lock(Clone::clone)
104 }
105
106 pub async fn get_updated_config() -> DetectorConfig {
107 DETECTOR_CONFIG_UPDATES.wait().await
108 }
109}