diff --git a/bptc19696.py b/bptc.py similarity index 76% rename from bptc19696.py rename to bptc.py index 2920756..a1b63cc 100755 --- a/bptc19696.py +++ b/bptc.py @@ -9,6 +9,7 @@ from __future__ import print_function from bitarray import bitarray import hamming +from time import time # Does anybody read this stuff? There's a PEP somewhere that says I should do this. __author__ = 'Cortney T. Buffington, N0MJS' @@ -43,7 +44,7 @@ INDEX_181 = ( # Converts a DMR frame using 98-68-98 (info-sync/EMB-info) into 196 bit array # Applies interleave indecies de-interleave 196 bit array -def deinterleave(_data): +def deinterleave_19696(_data): deint = bitarray(196, endian='big') for index in xrange(196): deint[index] = _data[INDEX_181[index]] # the real math is slower: deint[index] = _data[(index * 181) % 196] @@ -51,7 +52,7 @@ def deinterleave(_data): # Applies BTPC error detection/correction routines # This routine, in practice, will not be used in HBlink or DMRlink - it's only usefull for OTA direct data -def error_check(_data): +def error_check_19696(_data): count = 0 column = bitarray(13, endian='big') @@ -86,7 +87,7 @@ def error_check(_data): # BPTC(196,96) Encoding Routings #------------------------------------------------------------------------------ -def interleave(_data): +def interleave_19696(_data): inter = bitarray(196, endian='big') for index in xrange(196): inter[INDEX_181[index]] = _data[index] # the real math is slower: deint[index] = _data[(index * 181) % 196] @@ -94,7 +95,7 @@ def interleave(_data): # Accepts 12 byte LC header + RS1293, converts to binary and pads for 196 bit # encode hamming 15113 to rows and 1393 to columns -def encode(_data): +def encode_19696(_data): # Create a bitarray from the 4 bytes of LC data (includes RS1293 ECC) _bdata = bitarray(endian='big') _bdata.frombytes(_data) @@ -133,6 +134,42 @@ def encode(_data): return _bdata +#------------------------------------------------------------------------------ +# BPTC Embedded LC Decoding Routines +#------------------------------------------------------------------------------ + + +#------------------------------------------------------------------------------ +# BPTC Embedded LC Encoding Routines +#------------------------------------------------------------------------------ + + +# Accepts 12 byte LC header + 5-bit checksum, converts to binary and builts out the BPTC +# encoded result with hamming(16,11,4) and parity. +def encode_emblc(_lc, _csum5): + # Create a bitarray from the 4 bytes of LC data (includes 5-bit checksum). + _binlc = bitarray(endian='big') + _binlc.frombytes(_lc) + + # Insert the checksum bits at the right location in the matrix (this is actually faster than with a for loop) + _binlc.insert(32,_csum5[0]) + _binlc.insert(43,_csum5[1]) + _binlc.insert(54,_csum5[2]) + _binlc.insert(65,_csum5[3]) + _binlc.insert(76,_csum5[4]) + + # Insert the hamming bits at the right location in the matrix + for index in xrange(0,112,16): + for hindex,hbit in zip(xrange(index+11,index+16), hamming.enc_16114(_binlc[index:index+11])): + _binlc.insert(hindex,hbit) + + for index in xrange(0,16): + _binlc.insert(index+112, _binlc[index+0] ^ _binlc[index+16] ^ _binlc[index+32] ^ _binlc[index+48] ^ _binlc[index+64] ^ _binlc[index+80] ^ _binlc[index+96]) + + # TO DO NEXT: + # INTERLEAVE, RETURN A TUPLE OR LIBRARY OR EACH SEGMENT OF THE LC + # EACH SEGMENT IS 4 COLUMNS, TOP TO BOTTOM, LEFT TO RIGHT (PAGE 124 ETSI) + #------------------------------------------------------------------------------ # Used to execute the module directly to run built-in tests #------------------------------------------------------------------------------ @@ -141,6 +178,7 @@ if __name__ == '__main__': from binascii import b2a_hex as h from time import time + import crc def to_bytes(_bits): #add_bits = 8 - (len(_bits) % 8) @@ -154,8 +192,8 @@ if __name__ == '__main__': orig_data = '\x00\x10\x20\x00\x0c\x30\x2f\x9b\xe5\xda\xd4\x5a' t0 = time() - enc_data = encode(orig_data) - inter_data = interleave(enc_data) + enc_data = encode_19696(orig_data) + inter_data = interleave_19696(enc_data) t1 = time() encode_time = t1-t0 @@ -169,8 +207,8 @@ if __name__ == '__main__': dec_bits = dec_bits[0:98] + dec_bits[166:264] t0 = time() - deint_data = deinterleave(dec_bits) - err_corrected = error_check(deint_data) # This corrects deint_data in place -- it does not return a new array!!! + deint_data = deinterleave_19696(dec_bits) + err_corrected = error_check_19696(deint_data) # This corrects deint_data in place -- it does not return a new array!!! ext_data = to_bytes(deint_data) t1 = time() decode_time = t1-t0 @@ -195,4 +233,9 @@ if __name__ == '__main__': print('ENCODED vs. DECODED:') print('enc:', enc_data) print('dec:', deint_data) - print(enc_data == deint_data) \ No newline at end of file + print(enc_data == deint_data) + + orig_data = '\x00\x10\x20\x00\x0c\x30\x2f\x9b\xe5' + orig_csum = crc.csum5(orig_data) + emblc = encode_emblc(orig_data, orig_csum) + \ No newline at end of file diff --git a/crc.py b/crc.py index 18e0d05..c867b15 100755 --- a/crc.py +++ b/crc.py @@ -22,12 +22,14 @@ def csum5(_data): _data = bytearray(_data) accum = 0 assert len(_data) == 9, 'csum5 expected 9 bytes of data and got something else' + for i in xrange(9): accum += _data[i] accum = chr(accum % 31) csum = bitarray() csum.frombytes(accum) del csum[0:3] + return csum diff --git a/dmr_decon.py b/dmr_decon.py index be3c86d..241a136 100755 --- a/dmr_decon.py +++ b/dmr_decon.py @@ -9,7 +9,7 @@ from __future__ import print_function from bitarray import bitarray -import bptc19696 +import bptc import constants as const # Does anybody read this stuff? There's a PEP somewhere that says I should do this. @@ -37,7 +37,7 @@ def lc_data_9(_data): def voice_head_term(_string): burst = to_bits(_string) info = burst[0:98] + burst[166:264] - de_int_info = bptc19696.deinterleave(info) + de_int_info = bptc.deinterleave_19696(info) slot_type = burst[98:108] + burst[156:166] lc = to_bytes(lc_data_9(de_int_info)) cc = to_bytes(slot_type[0:4]) diff --git a/hamming.py b/hamming.py index dbfaa15..5bfb54f 100755 --- a/hamming.py +++ b/hamming.py @@ -117,6 +117,7 @@ def dec_1393(_data): # ENCODER - returns a bitarray object containing the hamming checksums def enc_16114(_data): + assert len(_data) == 11, 'Hamming Encoder 16,11,4: Data not 11 bits long' csum = bitarray(5) csum[0] = _data[0] ^ _data[1] ^ _data[2] ^ _data[3] ^ _data[5] ^ _data[7] ^ _data[8] csum[1] = _data[1] ^ _data[2] ^ _data[3] ^ _data[4] ^ _data[6] ^ _data[8] ^ _data[9]