Lucas Teske zrewidował ten Gist 9 years ago. Przejdź do rewizji
1 file changed, 357 insertions
soft-packet-finder.py(stworzono plik)
| @@ -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() | |
Nowsze
Starsze