Son aktivite 1 month ago

Soft Decision Bit LRPT Packet Finder (WIP)

racerxdl's Avatar Lucas Teske bu gisti düzenledi 9 years ago. Düzenlemeye git

1 file changed, 357 insertions

soft-packet-finder.py(dosya oluşturuldu)

@@ -0,0 +1,357 @@
1 + #!/usr/bin/env python
2 +
3 + # WARNING: Work-in-progress
4 +
5 + import os, math
6 + import collections
7 +
8 + ifile = "2016_08_17_LRPT_09-06-31.s" #"sample.s"
9 + ofile = "sample.s.out"#"sample.s.out"
10 + skipi = 0 #4800
11 +
12 + '''
13 + Sync Words Phased
14 +
15 + 0 = 00011010 11001111 11111100 00011101 = 0x1ACFFC1D
16 + 1 = 10001111 01100101 01010110 10000100 = 0x8F655684
17 + 2 = 11100101 00110000 00000011 11100010 = 0xE53003E2
18 + 3 = 01110000 10011010 10101001 01111011 = 0x709AA97B
19 +
20 +
21 +
22 + 10001111 01100101 01010110 10000100
23 + 01110000 10011010 10101001 01111011
24 +
25 + '''
26 +
27 + '''
28 + Sync Word in 1/2 k=7 FEC:
29 +
30 + 1111 1100 1010 0010 1011 0110 0011 1101 1011 0000 0000 1101 1001 0111 1001 0100 0xfca2b63db00d9794
31 + 0101 0110 1111 1011 1101 0011 1001 0100 1101 1010 1010 0100 1100 0001 1100 0010 0x56fbd394daa4c1c2
32 + 0000 0011 0101 1101 0100 1001 1100 0010 0100 1111 1111 0010 0110 1000 0110 1011 0x035d49c24ff2686b
33 + 1010 1001 0000 0100 0010 1100 0110 1011 0010 0101 0101 1011 0011 1110 0011 1101 0xa9042c6b255b3e3d
34 +
35 + also for IQ reversal, we reverse each pair of bits. Since I'm lazy, this script does the bit reversal over binary string:
36 +
37 + x = "1010 1001 0000 0100 0010 1100 0110 1011 0010 0101 0101 1011 0011 1110 0011 1101".replace(" ", "")
38 + o = ""
39 + for i in range(0, len(x), 2):
40 + o += x[i+1]
41 + o += x[i]
42 +
43 + print o
44 + print hex(int(o, 2))
45 +
46 + So for bit reversal we have this sync words:
47 +
48 + 1111 1100 0101 0001 0111 1001 0011 1110 0111 0000 0000 1110 0110 1011 0110 1000 0xfc51793e700e6b68
49 + 1010 1001 1111 0111 1110 0011 0110 1000 1110 0101 0101 1000 1100 0010 1100 0001 0xa9f7e368e558c2c1
50 + 0000 0011 1010 1110 1000 0110 1100 0001 1000 1111 1111 0001 1001 0100 1001 0111 0x03ae86c18ff19497
51 + 0101 0110 0000 1000 0001 1100 1001 0111 0001 1010 1010 0111 0011 1101 0011 1110 0x56081c971aa73d3e
52 +
53 + '''
54 +
55 + '''
56 + Frame Size = 1024 bytes (1020 + 4)
57 + Rate = 1/2
58 + Frame Symbol Size = 1024 * 8 * 2
59 +
60 + Input = IQ Byte. Symbol = 2 Byte
61 + Frame Input Size = 1024 * 8 * 2 * 2
62 + '''
63 +
64 + frameSymbolSize = 1024 * 8
65 + frameInputSize = frameSymbolSize * 2
66 + frameBitSize = frameSymbolSize * 2
67 + syncWordSize = 32
68 + syncWordDoubleSize = 64
69 +
70 + UW0 = 0xfca2b63db00d9794
71 + UW1 = 0x56fbd394daa4c1c2
72 + UW2 = 0x035d49c24ff2686b
73 + UW3 = 0xa9042c6b255b3e3d
74 +
75 + REVUW0 = 0xfc51793e700e6b68
76 + REVUW1 = 0xa9f7e368e558c2c1
77 + REVUW2 = 0x03ae86c18ff19497
78 + REVUW3 = 0x56081c971aa73d3e
79 +
80 + '''
81 + Tricky, we need a 2-bit group reversal for correcting IQ parameters.
82 + This could be done in several ways, but I will do as a Lookup Table.
83 + Basically for every index I in this element, there will be I with
84 + 2-bit group reversed output. If you're curious how I got this values,
85 + I was lazy also.
86 +
87 + def bit2rev(n):
88 + x = format(n, '#0{}b'.format(10))[2:] # Binary string of n
89 + o = "" # Reversed 2bit binary string
90 + for i in range(0, len(x), 2):
91 + o += x[i+1]
92 + o += x[i]
93 + return int(o, 2) # Return the integer
94 +
95 + BIT2REV = []
96 + for i in range(256):
97 + BIT2REV.append(bit2rev(i))
98 +
99 +
100 + So just for example: Lets supose we get a byte with value 123 that is IQ reversed.
101 + To un-reverse we go to the position 123 of the BIT2REV table that is: 183.
102 +
103 + So if we get the binary strings:
104 +
105 + 123 = 01 11 10 11
106 + 186 = 10 11 01 11
107 +
108 + So we inverted all 2 bit groups.
109 + '''
110 +
111 + BIT2REV = [
112 + 0, 2, 1, 3, 8, 10, 9, 11, 4, 6, 5, 7, 12, 14, 13, 15,
113 + 32, 34, 33, 35, 40, 42, 41, 43, 36, 38, 37, 39, 44, 46, 45, 47,
114 + 16, 18, 17, 19, 24, 26, 25, 27, 20, 22, 21, 23, 28, 30, 29, 31,
115 + 48, 50, 49, 51, 56, 58, 57, 59, 52, 54, 53, 55, 60, 62, 61, 63,
116 + 128, 130, 129, 131, 136, 138, 137, 139, 132, 134, 133, 135, 140, 142, 141, 143,
117 + 160, 162, 161, 163, 168, 170, 169, 171, 164, 166, 165, 167, 172, 174, 173, 175,
118 + 144, 146, 145, 147, 152, 154, 153, 155, 148, 150, 149, 151, 156, 158, 157, 159,
119 + 176, 178, 177, 179, 184, 186, 185, 187, 180, 182, 181, 183, 188, 190, 189, 191,
120 + 64, 66, 65, 67, 72, 74, 73, 75, 68, 70, 69, 71, 76, 78, 77, 79,
121 + 96, 98, 97, 99, 104, 106, 105, 107, 100, 102, 101, 103, 108, 110, 109, 111,
122 + 80, 82, 81, 83, 88, 90, 89, 91, 84, 86, 85, 87, 92, 94, 93, 95,
123 + 112, 114, 113, 115, 120, 122, 121, 123, 116, 118, 117, 119, 124, 126, 125, 127,
124 + 192, 194, 193, 195, 200, 202, 201, 203, 196, 198, 197, 199, 204, 206, 205, 207,
125 + 224, 226, 225, 227, 232, 234, 233, 235, 228, 230, 229, 231, 236, 238, 237, 239,
126 + 208, 210, 209, 211, 216, 218, 217, 219, 212, 214, 213, 215, 220, 222, 221, 223,
127 + 240, 242, 241, 243, 248, 250, 249, 251, 244, 246, 245, 247, 252, 254, 253, 255
128 + ]
129 +
130 + '''
131 + So for phase ambiguities we can also use a LUT. So we have four cases, but we
132 + only need to account for one: 90 degrees. Because:
133 + 0 deg is what we want
134 + 90 deg we will do a LUT for getting 0 deg
135 + 180 deg is the negate of 0 deg (so we can just xor by 0xFF)
136 + 270 deg is the negate of 90 deg (so we can xor by 0xFF and then use 90 deg LUT)
137 +
138 + So a 90 deg rotation in the constelation maps as:
139 + 0 deg => 90 deg
140 + 00 => 10
141 + 01 => 00
142 + 11 => 01
143 + 10 => 11
144 +
145 + So as usual:
146 +
147 + def phaseshift(n):
148 + x = format(n, '#0{}b'.format(10))[2:] # Binary string of n
149 + o = "" # 90 deg phased binary string
150 + for i in range(0, len(x), 2):
151 + o += "1" if x[i+1] == "0" else "0"
152 + o += "0" if x[i] == "0" else "1"
153 + return int(o, 2) # Return the integer
154 +
155 + PHASED = []
156 + for i in range(256):
157 + PHASED.append(phaseshift(i))
158 +
159 + '''
160 +
161 + PHASED = [
162 + 170, 168, 171, 169, 162, 160, 163, 161, 174, 172, 175, 173, 166, 164, 167, 165,
163 + 138, 136, 139, 137, 130, 128, 131, 129, 142, 140, 143, 141, 134, 132, 135, 133,
164 + 186, 184, 187, 185, 178, 176, 179, 177, 190, 188, 191, 189, 182, 180, 183, 181,
165 + 154, 152, 155, 153, 146, 144, 147, 145, 158, 156, 159, 157, 150, 148, 151, 149,
166 + 42, 40, 43, 41, 34, 32, 35, 33, 46, 44, 47, 45, 38, 36, 39, 37,
167 + 10, 8, 11, 9, 2, 0, 3, 1, 14, 12, 15, 13, 6, 4, 7, 5,
168 + 58, 56, 59, 57, 50, 48, 51, 49, 62, 60, 63, 61, 54, 52, 55, 53,
169 + 26, 24, 27, 25, 18, 16, 19, 17, 30, 28, 31, 29, 22, 20, 23, 21,
170 + 234, 232, 235, 233, 226, 224, 227, 225, 238, 236, 239, 237, 230, 228, 231, 229,
171 + 202, 200, 203, 201, 194, 192, 195, 193, 206, 204, 207, 205, 198, 196, 199, 197,
172 + 250, 248, 251, 249, 242, 240, 243, 241, 254, 252, 255, 253, 246, 244, 247, 245,
173 + 218, 216, 219, 217, 210, 208, 211, 209, 222, 220, 223, 221, 214, 212, 215, 213,
174 + 106, 104, 107, 105, 98, 96, 99, 97, 110, 108, 111, 109, 102, 100, 103, 101,
175 + 74, 72, 75, 73, 66, 64, 67, 65, 78, 76, 79, 77, 70, 68, 71, 69,
176 + 122, 120, 123, 121, 114, 112, 115, 113, 126, 124, 127, 125, 118, 116, 119, 117,
177 + 90, 88, 91, 89, 82, 80, 83, 81, 94, 92, 95, 93, 86, 84, 87, 85
178 + ]
179 +
180 +
181 + def binary(num, length=8):
182 + return format(num, '#0{}b'.format(length + 2))
183 +
184 + def binStringToIntSoftArr(b):
185 + if b[1] == 'b':
186 + b = b[2:]
187 + a = []
188 + for i in b:
189 + a.append(int(i) * 0xFF)
190 + return a
191 +
192 + def checkCorrelationInBuffer():
193 + uw0mc = 0 # Highest Correlation Factor for UW0
194 + uw0p = 0 # Highest Correlation Position for UW0
195 + uw1mc = 0
196 + uw1p = 0
197 + uw2mc = 0
198 + uw2p = 0
199 + uw3mc = 0
200 + uw3p = 0
201 + ruw0mc = 0 # Highest Correlation Factor for REVUW0
202 + ruw0p = 0 # Highest Correlation Position for REVUW0
203 + ruw1mc = 0
204 + ruw1p = 0
205 + ruw2mc = 0
206 + ruw2p = 0
207 + ruw3mc = 0
208 + ruw3p = 0
209 +
210 + for i in range(0, frameBitSize - syncWordDoubleSize):
211 + uw0c = 0
212 + uw1c = 0
213 + uw2c = 0
214 + uw3c = 0
215 + ruw0c = 0
216 + ruw1c = 0
217 + ruw2c = 0
218 + ruw3c = 0
219 + # To get the highest correlation, we xor with the word.
220 + for k in range(0, syncWordDoubleSize):
221 + uw0c += sbits[i+k] ^ UW0[k]
222 + uw1c += sbits[i+k] ^ UW1[k]
223 + uw2c += sbits[i+k] ^ UW2[k]
224 + uw3c += sbits[i+k] ^ UW3[k]
225 + ruw0c += sbits[i+k] ^ REVUW0[k]
226 + ruw1c += sbits[i+k] ^ REVUW1[k]
227 + ruw2c += sbits[i+k] ^ REVUW2[k]
228 + ruw3c += sbits[i+k] ^ REVUW3[k]
229 +
230 + uw0p = i if uw0c > uw0mc else uw0p
231 + uw1p = i if uw1c > uw1mc else uw1p
232 + uw2p = i if uw2c > uw2mc else uw2p
233 + uw3p = i if uw3c > uw3mc else uw3p
234 + ruw0p = i if ruw0c > ruw0mc else ruw0p
235 + ruw1p = i if ruw1c > ruw1mc else ruw1p
236 + ruw2p = i if ruw2c > ruw2mc else ruw2p
237 + ruw3p = i if ruw3c > ruw3mc else ruw3p
238 +
239 + uw0mc = uw0c if uw0c > uw0mc else uw0mc
240 + uw1mc = uw1c if uw1c > uw1mc else uw1mc
241 + uw2mc = uw2c if uw2c > uw2mc else uw2mc
242 + uw3mc = uw3c if uw3c > uw3mc else uw3mc
243 + ruw0mc = ruw0c if ruw0c > ruw0mc else ruw0mc
244 + ruw1mc = ruw1c if ruw1c > ruw1mc else ruw1mc
245 + ruw2mc = ruw2c if ruw2c > ruw2mc else ruw2mc
246 + ruw3mc = ruw3c if ruw3c > ruw3mc else ruw3mc
247 +
248 + return uw0p, uw0mc, uw1p, uw1mc, uw2p, uw2mc, uw3p, uw3mc, ruw0p, ruw0mc, ruw1p, ruw1mc, ruw2p, ruw2mc, ruw3p, ruw3mc
249 +
250 +
251 +
252 + UW0 = binStringToIntSoftArr(binary(UW0, syncWordDoubleSize))
253 + UW1 = binStringToIntSoftArr(binary(UW1, syncWordDoubleSize))
254 + UW2 = binStringToIntSoftArr(binary(UW2, syncWordDoubleSize))
255 + UW3 = binStringToIntSoftArr(binary(UW3, syncWordDoubleSize))
256 + REVUW0 = binStringToIntSoftArr(binary(REVUW0, syncWordDoubleSize))
257 + REVUW1 = binStringToIntSoftArr(binary(REVUW1, syncWordDoubleSize))
258 + REVUW2 = binStringToIntSoftArr(binary(REVUW2, syncWordDoubleSize))
259 + REVUW3 = binStringToIntSoftArr(binary(REVUW3, syncWordDoubleSize))
260 +
261 + f = open(ifile, "r")
262 + fsize = os.path.getsize(ifile)
263 + #o = open(ofile, "w")
264 + #ob = open(ofile + "bit", "w")
265 +
266 + sbits = collections.deque(maxlen=frameBitSize)
267 +
268 + count = 0
269 + fcount = 0
270 +
271 + f.seek(skipi)
272 + count += skipi
273 +
274 + print "Frame Input Size: %s" %frameInputSize
275 +
276 + while count < fsize:
277 + '''
278 + Read the data from input to sbits
279 + '''
280 + data = f.read(frameInputSize)
281 + for i in range(0, frameInputSize):
282 + sbits.append(ord(data[i]))
283 +
284 + '''
285 + Search for the sync word using correlation
286 + '''
287 +
288 + uw0p, uw0mc, uw1p, uw1mc, uw2p, uw2mc, uw3p, uw3mc, ruw0p, ruw0mc, ruw1p, ruw1mc, ruw2p, ruw2mc, ruw3p, ruw3mc = checkCorrelationInBuffer()
289 + mp = max(uw0mc, uw1mc, uw2mc, uw3mc, ruw0mc, ruw1mc, ruw2mc, ruw3mc)
290 +
291 + print "Frame: #%s" %fcount
292 + print "Max Correlation: %s" % (mp / 256)
293 + if mp == uw0mc:
294 + print "Max Correlation with 0 degrees Word at %s" % uw0p
295 + n = 0
296 + p = uw0p
297 + elif mp == uw1mc:
298 + print "Max Correlation with 90 degrees Word at %s" % uw1p
299 + n = 1
300 + p = uw1p
301 + elif mp == uw2mc:
302 + print "Max Correlation with 180 degrees Word at %s" % uw2p
303 + n = 2
304 + p = uw2p
305 + elif mp == uw3mc:
306 + print "Max Correlation with 270 degrees Word at %s" % uw3p
307 + n = 3
308 + p = uw3p
309 + elif mp == ruw0mc:
310 + print "Max Correlation with 0 degrees Word at %s Reverse IQ" % ruw0p
311 + n = 0
312 + p = ruw0p
313 + elif mp == ruw1mc:
314 + print "Max Correlation with 90 degrees Word at %s Reverse IQ" % ruw1p
315 + n = 1
316 + p = ruw1p
317 + elif mp == ruw2mc:
318 + print "Max Correlation with 180 degrees Word at %s Reverse IQ" % ruw2p
319 + n = 2
320 + p = ruw2p
321 + elif mp == ruw3mc:
322 + print "Max Correlation with 270 degrees Word at %s Reverse IQ" % ruw3p
323 + n = 3
324 + p = ruw3p
325 +
326 + if mp / 256 < 40:
327 + print "Frame Lock Error. Correlation less than 47 bits"
328 + count += frameInputSize
329 + else:
330 + '''
331 + Read p bits for syncing the Circle Buffer
332 + Each pair of bits come from 2 bytes of the input
333 + So we will read 1 byte per bit
334 + '''
335 + #p -= 12
336 + t = p if p % 2 == 0 else p + 1
337 + data = f.read(t)
338 + for i in range(0, t):
339 + sbits.append(ord(data[i]))
340 +
341 + '''
342 + Now we should have everything in sync
343 + '''
344 + #frame = processFrame(list(sbits), n)
345 + #o.write(frame)
346 + #frameb = processFrameBitMap(list(sbits), n)
347 + #ob.write(frameb)
348 + fcount += 1
349 + count += frameInputSize + t
350 +
351 + '''
352 + Clean everything
353 + '''
354 +
355 + f.close()
356 + o.close()
357 + ob.close()
Daha yeni Daha eski