Decode radio transmissions from devices on the ISM bands in OCaml
at main 156 lines 4.5 kB view raw
1(* Two-dimensional bit buffer *) 2 3let max_cols = 128 4let max_rows = 50 5 6type t = { 7 mutable num_rows : int; 8 mutable free_row : int; 9 bits_per_row : int array; 10 syncs_before_row : int array; 11 bb : bytes array; 12} 13 14let create () = 15 { 16 num_rows = 0; 17 free_row = 0; 18 bits_per_row = Array.make max_rows 0; 19 syncs_before_row = Array.make max_rows 0; 20 bb = Array.init max_rows (fun _ -> Bytes.make max_cols '\000'); 21 } 22 23let clear t = 24 t.num_rows <- 0; 25 t.free_row <- 0; 26 Array.fill t.bits_per_row 0 max_rows 0; 27 Array.fill t.syncs_before_row 0 max_rows 0; 28 Array.iter (fun b -> Bytes.fill b 0 max_cols '\000') t.bb 29 30let add_bit t bit = 31 if t.free_row < max_rows then begin 32 let row = t.free_row in 33 let bit_pos = t.bits_per_row.(row) in 34 if bit_pos < max_cols * 8 then begin 35 let byte_pos = bit_pos / 8 in 36 let bit_in_byte = 7 - (bit_pos mod 8) in 37 if bit <> 0 then begin 38 let b = Bytes.get_uint8 t.bb.(row) byte_pos in 39 Bytes.set_uint8 t.bb.(row) byte_pos (b lor (1 lsl bit_in_byte)) 40 end; 41 t.bits_per_row.(row) <- bit_pos + 1; 42 if t.num_rows = 0 then t.num_rows <- 1 43 end 44 end 45 46let add_row t = 47 if t.bits_per_row.(t.free_row) > 0 && t.free_row + 1 < max_rows then begin 48 t.free_row <- t.free_row + 1; 49 t.num_rows <- t.num_rows + 1 50 end 51 52let add_sync t = 53 if t.bits_per_row.(t.free_row) > 0 then add_row t 54 else t.syncs_before_row.(t.free_row) <- t.syncs_before_row.(t.free_row) + 1 55 56let num_rows t = t.num_rows 57let bits_per_row t row = if row < max_rows then t.bits_per_row.(row) else 0 58 59let syncs_before_row t row = 60 if row < max_rows then t.syncs_before_row.(row) else 0 61 62let get_row t row = if row < max_rows then t.bb.(row) else Bytes.empty 63 64let get_bit t ~row ~bit = 65 if row < max_rows && bit < t.bits_per_row.(row) then 66 let byte_pos = bit / 8 in 67 let bit_in_byte = 7 - (bit mod 8) in 68 (Bytes.get_uint8 t.bb.(row) byte_pos lsr bit_in_byte) land 1 69 else 0 70 71let get_byte t ~row ~bit_offset = 72 if row >= max_rows then 0 73 else 74 let b1 = Bytes.get_uint8 t.bb.(row) (bit_offset / 8) in 75 let b2 = 76 if bit_offset / 8 + 1 < max_cols then 77 Bytes.get_uint8 t.bb.(row) ((bit_offset / 8) + 1) 78 else 0 79 in 80 let shift = bit_offset mod 8 in 81 ((b1 lsl shift) lor (b2 lsr (8 - shift))) land 0xff 82 83let extract_bytes t ~row ~bit_offset ~len = 84 let num_bytes = (len + 7) / 8 in 85 let result = Bytes.make num_bytes '\000' in 86 for i = 0 to num_bytes - 1 do 87 Bytes.set_uint8 result i (get_byte t ~row ~bit_offset:(bit_offset + (i * 8))) 88 done; 89 result 90 91let invert t = 92 for row = 0 to t.num_rows - 1 do 93 let num_bytes = (t.bits_per_row.(row) + 7) / 8 in 94 for i = 0 to num_bytes - 1 do 95 Bytes.set_uint8 t.bb.(row) i (lnot (Bytes.get_uint8 t.bb.(row) i) land 0xff) 96 done 97 done 98 99let nrzs_decode _t = () (* TODO *) 100let nrzm_decode _t = () (* TODO *) 101 102let manchester_decode _t ~row ~start ~max = 103 ignore (row, start, max); 104 (create (), 0) 105 106let differential_manchester_decode _t ~row ~start ~max = 107 ignore (row, start, max); 108 (create (), 0) 109 110let search t ~row ~start ~pattern ~pattern_bits = 111 ignore (pattern, pattern_bits); 112 if row < max_rows then t.bits_per_row.(row) else start 113 114let compare_rows t ~row_a ~row_b ~max_bits = 115 ignore max_bits; 116 if row_a >= max_rows || row_b >= max_rows then 1 117 else if t.bits_per_row.(row_a) <> t.bits_per_row.(row_b) then 1 118 else Bytes.compare t.bb.(row_a) t.bb.(row_b) 119 120let count_repeats t ~row ~max_bits = 121 let count = ref 1 in 122 for i = 0 to t.num_rows - 1 do 123 if i <> row && compare_rows t ~row_a:row ~row_b:i ~max_bits = 0 then 124 incr count 125 done; 126 !count 127 128let find_repeated_row t ~min_repeats ~min_bits = 129 let rec check row = 130 if row >= t.num_rows then None 131 else if 132 t.bits_per_row.(row) >= min_bits 133 && count_repeats t ~row ~max_bits:0 >= min_repeats 134 then Some row 135 else check (row + 1) 136 in 137 check 0 138 139let find_repeated_prefix t ~min_repeats ~min_bits = 140 find_repeated_row t ~min_repeats ~min_bits 141 142let parse t _code = clear t (* TODO: implement parsing *) 143 144let row_to_string t row = 145 if row >= t.num_rows then "" 146 else 147 let bits = t.bits_per_row.(row) in 148 let num_bytes = (bits + 7) / 8 in 149 let hex = Rtl433_util.bytes_to_hex t.bb.(row) num_bytes in 150 Printf.sprintf "{%d} %s" bits hex 151 152let pp fmt t = 153 Format.fprintf fmt "Bitbuffer: %d rows@." t.num_rows; 154 for i = 0 to t.num_rows - 1 do 155 Format.fprintf fmt " [%d] %s@." i (row_to_string t i) 156 done