1#![no_std]
2#![allow(dead_code)]
3#![allow(unused_variables)]
4
5
6pub mod error;
8
9use crate::error::Error;
10
11pub mod data;
12use crate::data::{ AFE_GAIN, INTReg, INTType, LightningReg, Location, LocationMask, MinStrikes, Oscillator, StormFrontDistance, THRESHOLDS };
13
14pub mod constants;
15
16use crate::constants::DeviceAddress::{AD1_1_AD0_1, AD1_0_AD0_1, AD1_1_AD0_0, };
17use crate::constants::{ AS3935_POWER_MASK, AS3935_REG0x00, AS3935_REG0x01, AS3935_REG0x02, AS3935_REG0x03, AS3935_REG0x3A,
18 AS3935_REG0x3B, AS3935_REG0x3C, AS3935_REG0x3D, AS3935_REG0x04, AS3935_REG0x05, AS3935_REG0x06, AS3935_REG0x07,
19 AS3935_REG0x08, AS3953_DIRECT_COMMAND };
20
21
22#[cfg(not(feature = "async"))]
23use embedded_hal::{i2c::I2c, delay::DelayNs};
24#[cfg(feature = "async")]
25use embedded_hal_async::{i2c::I2c as AsyncI2c, delay::DelayNs as AsyncDelayNs};
26
27use log::{debug, info};
28use libm::{pow, truncf};
29
30
31pub struct AS3935<I2C, D> {
33 i2c: I2C,
35 address: u8,
37 delayer: D,
38
39}
40
41#[cfg(not(feature = "async"))]
42impl<I2C, D, E> AS3935<I2C, D>
43where
44 I2C: I2c<Error = E>,
45 D: DelayNs,
46{
47
48
49 pub fn new(i2c: I2C, address: u8, delayer: D) -> Self {
55 log::debug!("new called");
56 Self {
57 i2c,
58 address: address,
59 delayer,
60 }
61 }
62
63
64 pub fn release(self) -> I2C {
66 self.i2c
67 }
68
69}
70
71#[cfg(feature = "async")]
72impl<I2C, D, E> AS3935<I2C, D>
73where
74 I2C: AsyncI2c<Error = E>,
75 D: AsyncDelayNs,
76{
77 pub fn new(i2c: I2C, address: u8, delayer: D) -> Self {
83 debug!("new called");
84 Self {
85 i2c,
86 address: address,
87 delayer,
88 }
89 }
90
91 pub fn release(self) -> I2C {
93 self.i2c.release;
94 }
95
96}
97
98#[maybe_async_cfg::maybe(
99 sync(
100 cfg(not(feature = "async")),
101 self = "AS3935",
102 idents(AsyncI2c(sync = "I2c"), AsyncDelayNs(sync = "DelayNs"))
103 ),
104 async(feature = "async", keep_self)
105)]
106
107impl<I2C, D, E> AS3935<I2C, D>
108where
109 I2C: AsyncI2c<Error = E>,
110 D: AsyncDelayNs,
111{
112
113 async fn write_command<const N: usize>(&mut self, command_buf: [u8; N] ) -> Result<(), Error<E>> {
115 self.i2c
117 .write(self.address, &command_buf).await
118 .map_err(Error::I2c)?;
119 Ok(())
120 }
121
122 async fn read_register( &mut self, register_address: u8, buffer: &mut [u8] ) -> Result<(), Error<E>> {
123 let mut command_buffer = [0u8; 1];
124 command_buffer[0] = register_address;
125 self.i2c
127 .write_read(self.address, &command_buffer, buffer).await
128 .map_err(Error::I2c)?;
129 Ok(())
130 }
131
132
133
134 pub async fn calibrate_osc(&mut self) -> Result<(), Error<E>> {
136 debug!("in calibrate_osc");
137 self.write_command([AS3935_REG0x3D, AS3953_DIRECT_COMMAND]).await?;
138 self.display_oscillator(true, Oscillator::TRCO);
139 self.delayer.delay_ms(2).await;
140 self.display_oscillator(false, Oscillator::TRCO);
141
142 let mut result_buf: [u8; 1] = [0; 1];
144 self.read_register(AS3935_REG0x3B, &mut result_buf).await?;
145 let srco: bool = ((result_buf[0] & 0x40) >> 6) != 0; self.read_register(AS3935_REG0x3A, &mut result_buf).await?;
147 let trco: bool = ((result_buf[0] & 0x40) >> 6) != 0; if (srco || trco) {
149 return Err(Error::OscFailedCalibration);
150 } else {
151 return Ok(());
152 }
153 }
154
155
156 pub async fn reset_settings(&mut self) -> Result<(), Error<E>> {
158 debug!("in reset_settings");
159 self.write_command([AS3935_REG0x3C, AS3953_DIRECT_COMMAND]).await?;
160 Ok(())
161 }
162
163 pub async fn get_lightning_energy(&mut self) -> Result<u32, Error<E>> {
165 debug!("in get_lightning_energy");
166 let mut result_buf: [u8; 1] = [0; 1];
167 self.read_register(AS3935_REG0x06, &mut result_buf).await?;
168 let mmsb: u8 = (result_buf[0] & 0x3f);
169 self.read_register(AS3935_REG0x05, &mut result_buf).await?;
170 let msb: u8 = result_buf[0];
171 self.read_register(AS3935_REG0x04, &mut result_buf).await?;
172 let lsb: u8 = result_buf[0];
173 let bytes: [u8; 4] = [0x00, mmsb, msb, lsb];
174 let value: u32 = u32::from_be_bytes(bytes);
175 return Ok(value);
176
177 }
178
179 pub async fn display_oscillator(&mut self, state: bool, osc: Oscillator) -> Result<(), Error<E>> {
183 debug!("in display_oscillator");
184 let mut result_buf: [u8; 1] = [0; 1];
185 self.read_register(AS3935_REG0x08, &mut result_buf).await?;
186 let mut value : u8 = result_buf[0] | (osc as u8);
187 if (state) { self.write_command([AS3935_REG0x08, value]).await?;
189 } else { value = result_buf[0] & !(osc as u8);
191 self.write_command([AS3935_REG0x08, value]).await?;
192 }
193 Ok(())
194 }
195
196
197 pub async fn get_distance_to_storm(&mut self) -> Result<StormFrontDistance, Error<E>> {
199 debug!("in get_distance_to_storm");
200 let mut result_buf: [u8; 1] = [0; 1];
201 self.read_register(AS3935_REG0x07, &mut result_buf).await?;
202 let distance: u8 = result_buf[0] & 0x3f;
203 let mut storm_front_distance: StormFrontDistance = StormFrontDistance::OutOfRange;
204 if (distance == 0x3f) {
205 storm_front_distance = StormFrontDistance::OutOfRange;
206 } else if (distance == 0x01) {
207 storm_front_distance = StormFrontDistance::Overhead;
208 } else {
209 storm_front_distance = StormFrontDistance::Range_km(distance);
210 }
211 Ok(storm_front_distance)
212 }
213
214 pub async fn power_down(&mut self) -> Result<(), Error<E>> {
217 debug!("in power_down");
218 self.write_command([AS3935_REG0x00, AS3935_POWER_MASK ]).await?;
219 Ok(())
220 }
221
222 pub async fn set_indoor_outdoor(&mut self, location: Location) -> Result<(), Error<E>> {
224 debug!("in set_indoor_outdoor({:?})", location);
225 let mut location_mask = LocationMask::Indoor;
226 info!(" location is {:?} hex = {:02x}", location, location as u8);
227
228 if (location == Location::Indoor) {
229 location_mask = LocationMask::Indoor;
230 } else {
231 location_mask = LocationMask::Outdoor;
232 }
233
234 debug!(" location_mask = {:02x}", location_mask as u8);
235 let mut afe_gain: AFE_GAIN = AFE_GAIN(0x00);
236 afe_gain.set_location_mask(location_mask as u8);
237 debug!(" afe_gain is {:02x}", afe_gain.0);
238 self.write_command([AS3935_REG0x00, (afe_gain.0 as u8)]).await?;
239 Ok(())
240 }
241
242 pub async fn get_indoor_outdoor(&mut self) -> Result<Location, Error<E>> {
244 debug!("in get_indoor_outdoor");
245 let mut result_buf: [u8; 1] = [0; 1];
246 self.read_register(AS3935_REG0x00, &mut result_buf).await?;
247 debug!(" reg0x00 = {:02x}", result_buf[0]);
248 let afe_gain: AFE_GAIN = AFE_GAIN(result_buf[0]);
249 debug!(" afe_gain in hex = {:02x}", afe_gain.0);
250 debug!(" afe_gain = {:?}", afe_gain);
251 let mut where_is_it = Location::Indoor;
252 if (afe_gain.get_location_mask() == LocationMask::Indoor) {
253 where_is_it = Location::Indoor;
254 } else if (afe_gain.get_location_mask() == LocationMask::Outdoor) {
255 where_is_it = Location::Outdoor;
256 } else {
257 return Err(Error::ResponseError);
258 }
259 return Ok(where_is_it);
260 }
261
262 pub async fn get_interrupt_register(&mut self) -> Result<INTType, Error<E>> {
264 debug!("in get_interrupt_register");
265 let mut result_buf: [u8; 1] = [0; 1];
266 self.read_register(AS3935_REG0x03, &mut result_buf).await?;
267 let int_reg: INTReg = INTReg(result_buf[0]);
268 let int_type: INTType = int_reg.get_int_type();
269 Ok(int_type)
270 }
271
272 pub async fn wakeup(&mut self) -> Result<(), Error<E>> {
284 debug!("in wakeup");
285 let mut result_buf: [u8; 1] = [0; 1];
286 self.read_register(AS3935_REG0x3A, &mut result_buf).await?;
287 let mut afe_gain: AFE_GAIN = AFE_GAIN(result_buf[0]);
288 afe_gain.set_powerdown(false); self.write_command([AS3935_REG0x3A, afe_gain.0]).await?;
290 self.calibrate_osc().await?;
291 Ok(())
292
293 }
294
295 pub async fn set_watchdog_threshold(&mut self, threshold: u8 ) -> Result<(), Error<E>> {
297 debug!("in set_watchdog_threshold");
298 if (threshold > 10) {
299 return Err(Error::ValueLimit);
300 }
301 let mut result_buf: [u8; 1] = [0; 1];
302 self.read_register(AS3935_REG0x01, &mut result_buf).await?;
303 let mut threshold_reg: THRESHOLDS = THRESHOLDS(result_buf[0]);
304 threshold_reg.set_wd_threshold(threshold as u8);
305 self.write_command([AS3935_REG0x01, threshold_reg.0]).await?;
306 Ok(())
307 }
308
309 pub async fn get_watchdog_threshold(&mut self) -> Result<u8, Error<E>> {
311 debug!("in get_watchdog_threshold");
312 let mut result_buf: [u8; 1] = [0; 1];
313 self.read_register(AS3935_REG0x01, &mut result_buf).await?;
314 let threshold_reg: THRESHOLDS = THRESHOLDS(result_buf[0]);
315 let threshold = threshold_reg.get_wd_threshold();
316 Ok(threshold)
317 }
318
319 pub async fn set_noise_level(&mut self, level: u8 ) -> Result<(), Error<E>> {
321 debug!("in set_noise_level");
322 if (level > 7) {
323 return Err(Error::ValueLimit);
324 }
325 let mut result_buf: [u8; 1] = [0; 1];
326 self.read_register(AS3935_REG0x01, &mut result_buf).await?;
327 let mut threshold_reg: THRESHOLDS = THRESHOLDS(result_buf[0]);
328 threshold_reg.set_noise_floor(level);
329 self.write_command([AS3935_REG0x01, threshold_reg.0]).await?;
330 Ok(())
331 }
332
333 pub async fn get_noise_level(&mut self) -> Result<u8, Error<E>> {
335 debug!("in get_noise_level");
336 let mut result_buf: [u8; 1] = [0; 1];
337 self.read_register(AS3935_REG0x01, &mut result_buf).await?;
338 let threshold_reg: THRESHOLDS = THRESHOLDS(result_buf[0]);
339 let level = threshold_reg.get_noise_floor();
340 Ok(level)
341 }
342
343 pub async fn set_lightning_threshold(&mut self, threshold: MinStrikes ) -> Result<(), Error<E>> {
345 debug!("in set_lightning_threshold");
346 let mut result_buf: [u8; 1] = [0; 1];
347 self.read_register(AS3935_REG0x02, &mut result_buf).await?;
348 let mut lightning_reg: LightningReg = LightningReg(result_buf[0]);
349 lightning_reg.set_min_strikes(threshold as u8);
350 self.write_command([AS3935_REG0x02, lightning_reg.0]).await?;
351 Ok(())
352 }
353
354 pub async fn get_lightning_threshold(&mut self) -> Result<MinStrikes, Error<E>> {
356 debug!("in get_lightning_threshold");
357 let mut result_buf: [u8; 1] = [0; 1];
358 self.read_register(AS3935_REG0x02, &mut result_buf).await?;
359 let lightning_reg: LightningReg = LightningReg(result_buf[0]);
360 let min_strikes: MinStrikes = lightning_reg.get_min_strikes();
361 Ok(min_strikes)
362 }
363
364 pub async fn clear_statistics(&mut self) -> Result<(), Error<E>> {
366 debug!("in clear_statistics");
367 let mut result_buf: [u8; 1] = [0; 1];
368 self.read_register(AS3935_REG0x02, &mut result_buf).await?;
369 let mut lightning_reg: LightningReg = LightningReg(result_buf[0]);
370 lightning_reg.set_clear_stats(true);
371 debug!(" writing lightning_reg = {:?}", lightning_reg);
372 self.write_command([AS3935_REG0x02, lightning_reg.0]).await?;
373 Ok(())
374 }
375
376 pub async fn set_mask_disturber(&mut self, enable: bool) -> Result<(), Error<E>> {
378 debug!("in set_mask_disturber");
379 let mut result_buf: [u8; 1] = [0; 1];
380 self.read_register(AS3935_REG0x03, &mut result_buf).await?;
381 let mut int_reg: INTReg = INTReg(result_buf[0]);
382 int_reg.set_mask_dist(enable);
383 self.write_command([AS3935_REG0x03, int_reg.0]).await?;
384 Ok(())
385 }
386
387 pub async fn get_mask_disturber(&mut self) -> Result<bool, Error<E>> {
389 debug!("in get_mask_disturber");
390 let mut result_buf: [u8; 1] = [0; 1];
391 self.read_register(AS3935_REG0x03, &mut result_buf).await?;
392 let int_reg: INTReg = INTReg(result_buf[0]);
393 Ok(int_reg.get_mask_dist())
394 }
395
396 pub async fn set_spike_rejection(&mut self, sensitivity: u8) -> Result<(), Error<E>> {
398 debug!("in set_spike_rejection");
399 if (sensitivity > 15) {
400 return Err(Error::ValueLimit);
401 }
402 let mut result_buf: [u8; 1] = [0; 1];
403 self.read_register(AS3935_REG0x02, &mut result_buf).await?;
404 let mut lightning_reg: LightningReg = LightningReg(result_buf[0]);
405 lightning_reg.set_spike_reject(sensitivity);
406 self.write_command([AS3935_REG0x02, lightning_reg.0]).await?;
407 Ok(())
408 }
409
410 pub async fn get_spike_rejection(&mut self) -> Result<u8, Error<E>> {
412 debug!("in get_spike_rejection");
413 let mut result_buf: [u8; 1] = [0; 1];
414 let mut result_buf: [u8; 1] = [0; 1];
415 self.read_register(AS3935_REG0x02, &mut result_buf).await?;
416 let mut lightning_reg: LightningReg = LightningReg(result_buf[0]);
417 let sensitivity = lightning_reg.get_spike_reject();
418 Ok(sensitivity)
419 }
420
421 pub async fn set_antenna_div_ratio(&mut self, ratio: u8) -> Result<(), Error<E>> {
424 debug!("in set_antenna_div_ratio ( {} )", ratio);
425 let mut value: u8 = 0;
426 if (ratio == 16) {
427 value = 0;
428 } else if (ratio == 32) {
429 value = 1;
430 } else if { ratio == 64} {
431 value = 2;
432 } else if (ratio == 128) {
433 value = 3;
434 } else {
435 return Err(Error::ValueLimit);
436 }
437
438 let mut result_buf: [u8; 1] = [0; 1];
439 self.read_register(AS3935_REG0x03, &mut result_buf).await?;
440 let mut int_reg: INTReg = INTReg(result_buf[0]);
441 int_reg.set_freq_div(value);
442 self.write_command([AS3935_REG0x03, int_reg.0]).await?;
444 Ok(())
445 }
446
447 pub async fn get_antenna_div_ratio(&mut self) -> Result<u8, Error<E>> {
449 debug!("in get_antenna_div_ratio");
450 let mut result_buf: [u8; 1] = [0; 1];
451 self.read_register(AS3935_REG0x03, &mut result_buf).await?;
452 let mut int_reg: INTReg = INTReg(result_buf[0]);
453 let value = int_reg.get_freq_div();
454 let return_value: u8 = (1 << (value + 4));
455 Ok((return_value))
456 }
457
458 pub async fn set_tuning_cap(&mut self, p_farads: u8) -> Result<(), Error<E>> {
461 debug!("in set_tuning_cap( {:02x} )", p_farads);
462 if (p_farads > 128) {
463 return Err(Error::ValueLimit);
464 } else if ((p_farads % 8) != 0) {
465 debug!(" bummer, not modulo 8");
466 return Err(Error::ValueLimit);
467 }
468 let mut result_buf: [u8; 1] = [0; 1];
469 self.read_register(AS3935_REG0x08, &mut result_buf).await?;
470 let mut new_value: u8 = (result_buf[0]) | ((p_farads >> 3) & 0x17);
471 self.write_command([AS3935_REG0x08, new_value]).await?;
473
474 Ok(())
475 }
476
477 pub async fn get_tuning_cap(&mut self) -> Result<u8, Error<E>> {
479 debug!("in get_tuning_cap");
480 let mut result_buf: [u8; 1] = [0; 1];
481 self.read_register(AS3935_REG0x08, &mut result_buf).await?;
482 let p_farads: u8 = (result_buf[0] & 0x1f) << 3; Ok(p_farads)
484 }
485
486
487}