Decode radio transmissions from devices on the ISM bands in OCaml
1(* Pulse timing data *)
2
3let max_pulses = 1200
4let min_pulses = 16
5
6type t = {
7 offset : int64;
8 sample_rate : int;
9 depth_bits : int;
10 start_ago : int;
11 end_ago : int;
12 num_pulses : int;
13 pulses : int array;
14 gaps : int array;
15 ook_low_estimate : int;
16 ook_high_estimate : int;
17 fsk_f1_est : int;
18 fsk_f2_est : int;
19 freq1_hz : float;
20 freq2_hz : float;
21 centerfreq_hz : float;
22 range_db : float;
23 rssi_db : float;
24 snr_db : float;
25 noise_db : float;
26}
27
28let create ?(sample_rate = 250000) () =
29 {
30 offset = 0L;
31 sample_rate;
32 depth_bits = 8;
33 start_ago = 0;
34 end_ago = 0;
35 num_pulses = 0;
36 pulses = Array.make max_pulses 0;
37 gaps = Array.make max_pulses 0;
38 ook_low_estimate = 0;
39 ook_high_estimate = 0;
40 fsk_f1_est = 0;
41 fsk_f2_est = 0;
42 freq1_hz = 0.0;
43 freq2_hz = 0.0;
44 centerfreq_hz = 0.0;
45 range_db = 0.0;
46 rssi_db = 0.0;
47 snr_db = 0.0;
48 noise_db = 0.0;
49 }
50
51let clear t = { t with num_pulses = 0 }
52
53let add_pulse t ~pulse ~gap =
54 if t.num_pulses >= max_pulses then None
55 else begin
56 t.pulses.(t.num_pulses) <- pulse;
57 t.gaps.(t.num_pulses) <- gap;
58 Some { t with num_pulses = t.num_pulses + 1 }
59 end
60
61let samples_to_us t samples =
62 Float.of_int samples *. 1_000_000.0 /. Float.of_int t.sample_rate
63
64let us_to_samples t us = int_of_float (us *. Float.of_int t.sample_rate /. 1_000_000.0)
65
66let pulse_us t idx =
67 if idx < t.num_pulses then samples_to_us t t.pulses.(idx) else 0.0
68
69let gap_us t idx =
70 if idx < t.num_pulses then samples_to_us t t.gaps.(idx) else 0.0
71
72let total_samples t =
73 let sum = ref 0 in
74 for i = 0 to t.num_pulses - 1 do
75 sum := !sum + t.pulses.(i) + t.gaps.(i)
76 done;
77 !sum
78
79let total_us t = samples_to_us t (total_samples t)
80
81let exceeds_gap_limit t gap_limit_us =
82 let limit_samples = us_to_samples t gap_limit_us in
83 let rec check i =
84 if i >= t.num_pulses then false
85 else if t.gaps.(i) > limit_samples then true
86 else check (i + 1)
87 in
88 check 0
89
90let pp fmt t =
91 Format.fprintf fmt "PulseData: %d pulses, %.1f us total@." t.num_pulses
92 (total_us t)
93
94let to_string t = Format.asprintf "%a" pp t