MAJOR PROGRESS with LCs
This commit is contained in:
parent
67d18bbfdd
commit
6fb92d0808
210
bptc.py
210
bptc.py
@ -8,8 +8,7 @@
|
||||
|
||||
from __future__ import print_function
|
||||
from bitarray import bitarray
|
||||
import hamming
|
||||
from time import time
|
||||
import hamming, crc, rs129
|
||||
|
||||
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
||||
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||
@ -42,46 +41,21 @@ INDEX_181 = (
|
||||
# BPTC(196,96) Decoding Routings
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# 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_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]
|
||||
return deint
|
||||
|
||||
# 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_19696(_data):
|
||||
count = 0
|
||||
column = bitarray(13, endian='big')
|
||||
|
||||
while True:
|
||||
errors = False
|
||||
for col in xrange(15):
|
||||
pos = col + 1
|
||||
for index in xrange(13):
|
||||
column[index] = _data[pos]
|
||||
pos += 15
|
||||
|
||||
result_1393 = hamming.dec_1393(column)
|
||||
if result_1393[1]:
|
||||
pos = col + 1
|
||||
for index in xrange(13):
|
||||
_data[pos] = result_1393[0][index]
|
||||
pos += 15
|
||||
errors = True
|
||||
|
||||
for index in xrange(9):
|
||||
pos = (index*15) + 1
|
||||
result_15113 = hamming.dec_15113(_data[pos:(pos+15)])
|
||||
if result_15113[1]:
|
||||
errors = True
|
||||
_data[pos:(pos+15)] = result_15113[0]
|
||||
|
||||
count += 1
|
||||
if not errors or count > 4: break
|
||||
return (errors)
|
||||
def decode_full_lc(_data):
|
||||
binlc = bitarray(endian='big')
|
||||
binlc.extend([_data[136],_data[121],_data[106],_data[91], _data[76], _data[61], _data[46], _data[31]])
|
||||
binlc.extend([_data[152],_data[137],_data[122],_data[107],_data[92], _data[77], _data[62], _data[47], _data[32], _data[17], _data[2] ])
|
||||
binlc.extend([_data[123],_data[108],_data[93], _data[78], _data[63], _data[48], _data[33], _data[18], _data[3], _data[184],_data[169]])
|
||||
binlc.extend([_data[94], _data[79], _data[64], _data[49], _data[34], _data[19], _data[4], _data[185],_data[170],_data[155],_data[140]])
|
||||
binlc.extend([_data[65], _data[50], _data[35], _data[20], _data[5], _data[186],_data[171],_data[156],_data[141],_data[126],_data[111]])
|
||||
binlc.extend([_data[36], _data[21], _data[6], _data[187],_data[172],_data[157],_data[142],_data[127],_data[112],_data[97], _data[82] ])
|
||||
binlc.extend([_data[7], _data[188],_data[173],_data[158],_data[143],_data[128],_data[113],_data[98], _data[83]])
|
||||
'''
|
||||
This is the rest of the Full LC data -- the RS1293 FEC that we don't need
|
||||
_data[68],_data[53],_data[174],_data[159],_data[144],_data[129],_data[114],_data[99],_data[84],_data[69],_data[54],_data[39],
|
||||
_data[24],_data[145],_data[130],_data[115],_data[100],_data[85],_data[70],_data[55],_data[40],_data[25],_data[10],_data[191]
|
||||
'''
|
||||
return binlc
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# BPTC(196,96) Encoding Routings
|
||||
@ -133,11 +107,31 @@ def encode_19696(_data):
|
||||
|
||||
return _bdata
|
||||
|
||||
|
||||
def encode_header_lc(_lc):
|
||||
full_lc = _lc + rs129.lc_header_encode(_lc)
|
||||
full_lc = encode_19696(full_lc)
|
||||
full_lc = interleave_19696(full_lc)
|
||||
return full_lc
|
||||
|
||||
def encode_terminator_lc(_lc):
|
||||
lc_rs = _lc + rs129.lc_terminator_encode(_lc)
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# BPTC Embedded LC Decoding Routines
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
def decode_emblc(_elc_b, _elc_c, _elc_d, _elc_e):
|
||||
|
||||
_binlc = bitarray(endian='big')
|
||||
_binlc.extend([_elc_b[0],_elc_b[8], _elc_b[16],_elc_b[24],_elc_c[0],_elc_c[8], _elc_c[16],_elc_c[24],_elc_d[0],_elc_d[8] ,_elc_d[16]])
|
||||
_binlc.extend([_elc_b[1],_elc_b[9], _elc_b[17],_elc_b[25],_elc_c[1],_elc_c[9], _elc_c[17],_elc_c[25],_elc_d[1],_elc_d[9] ,_elc_d[17]])
|
||||
_binlc.extend([_elc_b[2],_elc_b[10],_elc_b[18],_elc_b[26],_elc_c[2],_elc_c[10],_elc_c[18],_elc_c[26],_elc_d[2],_elc_d[10]])
|
||||
_binlc.extend([_elc_b[3],_elc_b[11],_elc_b[19],_elc_b[27],_elc_c[3],_elc_c[11],_elc_c[19],_elc_c[27],_elc_d[3],_elc_d[11]])
|
||||
_binlc.extend([_elc_b[4],_elc_b[12],_elc_b[20],_elc_b[28],_elc_c[4],_elc_c[12],_elc_c[20],_elc_c[28],_elc_d[4],_elc_d[12]])
|
||||
_binlc.extend([_elc_b[5],_elc_b[13],_elc_b[21],_elc_b[29],_elc_c[5],_elc_c[13],_elc_c[21],_elc_c[29],_elc_d[5],_elc_d[13]])
|
||||
_binlc.extend([_elc_b[6],_elc_b[14],_elc_b[22],_elc_b[30],_elc_c[6],_elc_c[14],_elc_c[22],_elc_c[30],_elc_d[6],_elc_d[14]])
|
||||
|
||||
return(_binlc.tobytes())
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# BPTC Embedded LC Encoding Routines
|
||||
@ -146,17 +140,21 @@ def encode_19696(_data):
|
||||
|
||||
# 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):
|
||||
def encode_emblc(_lc):
|
||||
|
||||
# Get the 5-bit checksum for the Embedded LC
|
||||
_csum = crc.csum5(_lc)
|
||||
|
||||
# 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])
|
||||
_binlc.insert(32,_csum[0])
|
||||
_binlc.insert(43,_csum[1])
|
||||
_binlc.insert(54,_csum[2])
|
||||
_binlc.insert(65,_csum[3])
|
||||
_binlc.insert(76,_csum[4])
|
||||
|
||||
# Insert the hamming bits at the right location in the matrix
|
||||
for index in xrange(0,112,16):
|
||||
@ -167,85 +165,81 @@ def encode_emblc(_lc, _csum5):
|
||||
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])
|
||||
|
||||
t0 = time()
|
||||
emblc_a = bitarray(endian='big')
|
||||
emblc_a.extend([_binlc[0],_binlc[16],_binlc[32],_binlc[48],_binlc[64],_binlc[80],_binlc[96],_binlc[112]])
|
||||
emblc_a.extend([_binlc[1],_binlc[17],_binlc[33],_binlc[49],_binlc[65],_binlc[81],_binlc[97],_binlc[113]])
|
||||
emblc_a.extend([_binlc[2],_binlc[18],_binlc[34],_binlc[50],_binlc[66],_binlc[82],_binlc[98],_binlc[114]])
|
||||
emblc_a.extend([_binlc[3],_binlc[19],_binlc[35],_binlc[51],_binlc[67],_binlc[83],_binlc[99],_binlc[115]])
|
||||
t1 = time()
|
||||
print(t1-t0)
|
||||
# Create Embedded LC segments in 48 bit blocks
|
||||
emblc_b = bitarray(endian='big')
|
||||
emblc_b.extend([_binlc[0], _binlc[16],_binlc[32],_binlc[48],_binlc[64],_binlc[80],_binlc[96], _binlc[112]])
|
||||
emblc_b.extend([_binlc[1], _binlc[17],_binlc[33],_binlc[49],_binlc[65],_binlc[81],_binlc[97], _binlc[113]])
|
||||
emblc_b.extend([_binlc[2], _binlc[18],_binlc[34],_binlc[50],_binlc[66],_binlc[82],_binlc[98], _binlc[114]])
|
||||
emblc_b.extend([_binlc[3], _binlc[19],_binlc[35],_binlc[51],_binlc[67],_binlc[83],_binlc[99], _binlc[115]])
|
||||
|
||||
# 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)
|
||||
emblc_c = bitarray(endian='big')
|
||||
emblc_c.extend([_binlc[4], _binlc[20],_binlc[36],_binlc[52],_binlc[68],_binlc[84],_binlc[100],_binlc[116]])
|
||||
emblc_c.extend([_binlc[5], _binlc[21],_binlc[37],_binlc[53],_binlc[69],_binlc[85],_binlc[101],_binlc[117]])
|
||||
emblc_c.extend([_binlc[6], _binlc[22],_binlc[38],_binlc[54],_binlc[70],_binlc[86],_binlc[102],_binlc[118]])
|
||||
emblc_c.extend([_binlc[7], _binlc[23],_binlc[39],_binlc[55],_binlc[71],_binlc[87],_binlc[103],_binlc[119]])
|
||||
|
||||
emblc_d = bitarray(endian='big')
|
||||
emblc_d.extend([_binlc[8], _binlc[24],_binlc[40],_binlc[56],_binlc[72],_binlc[88],_binlc[104],_binlc[120]])
|
||||
emblc_d.extend([_binlc[9], _binlc[24],_binlc[41],_binlc[57],_binlc[73],_binlc[89],_binlc[105],_binlc[121]])
|
||||
emblc_d.extend([_binlc[10],_binlc[26],_binlc[42],_binlc[58],_binlc[74],_binlc[90],_binlc[106],_binlc[122]])
|
||||
emblc_d.extend([_binlc[11],_binlc[27],_binlc[43],_binlc[59],_binlc[75],_binlc[91],_binlc[107],_binlc[123]])
|
||||
|
||||
emblc_e = bitarray(endian='big')
|
||||
emblc_e.extend([_binlc[12],_binlc[28],_binlc[44],_binlc[60],_binlc[76],_binlc[92],_binlc[108],_binlc[124]])
|
||||
emblc_e.extend([_binlc[13],_binlc[29],_binlc[45],_binlc[61],_binlc[77],_binlc[93],_binlc[109],_binlc[125]])
|
||||
emblc_e.extend([_binlc[14],_binlc[30],_binlc[46],_binlc[62],_binlc[78],_binlc[94],_binlc[110],_binlc[126]])
|
||||
emblc_e.extend([_binlc[15],_binlc[31],_binlc[47],_binlc[63],_binlc[79],_binlc[95],_binlc[111],_binlc[127]])
|
||||
|
||||
return([emblc_b, emblc_c, emblc_d, emblc_e])
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Used to execute the module directly to run built-in tests
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
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)
|
||||
#if add_bits < 8:
|
||||
# for bit in xrange(add_bits):
|
||||
# _bits.insert(0,0)
|
||||
_string = _bits.tobytes()
|
||||
return _string
|
||||
|
||||
# Validation Example
|
||||
|
||||
orig_data = '\x00\x10\x20\x00\x0c\x30\x2f\x9b\xe5\xda\xd4\x5a'
|
||||
|
||||
# Header LC -- Terminator similar
|
||||
lc = '\x00\x10\x20\x00\x0c\x30\x2f\x9b\xe5' # \xda\xd4\x5a
|
||||
t0 = time()
|
||||
enc_data = encode_19696(orig_data)
|
||||
inter_data = interleave_19696(enc_data)
|
||||
full_lc_encode = encode_header_lc(lc)
|
||||
t1 = time()
|
||||
encode_time = t1-t0
|
||||
|
||||
# Good Data
|
||||
dec_data = '\x2b\x60\x04\x10\x1f\x84\x2d\xd0\x0d\xf0\x7d\x41\x04\x6d\xff\x57\xd7\x5d\xf5\xde\x30\x15\x2e\x20\x70\xb2\x0f\x80\x3f\x88\xc6\x95\xe2'
|
||||
# Bad Data
|
||||
#dec_data = '\x2b\x60\xff\xff\xff\x85\x2d\xd0\x0d\xf0\x7d\x41\x04\x6d\xff\x57\xd7\x5d\xf5\xde\x30\x15\x2e\x20\x70\xb2\x0f\x80\x3f\x88\xc6\x95\xe2'
|
||||
t0 = time()
|
||||
full_lc_dec = decode_full_lc(full_lc_encode)
|
||||
t1 = time()
|
||||
lc_decode_time = t1-t0
|
||||
|
||||
dec_bits = bitarray(endian='big')
|
||||
dec_bits.frombytes(dec_data)
|
||||
dec_bits = dec_bits[0:98] + dec_bits[166:264]
|
||||
print('VALIDATION ROUTINES:')
|
||||
print('Original Data: {}, {} bytes'.format(h(lc), len(lc)))
|
||||
print()
|
||||
print('BPTC(196,96):')
|
||||
print('Encoded data: {}, {} bytes'.format(h(full_lc_encode.tobytes()), len(full_lc_encode.tobytes())))
|
||||
print('Encoding time: {} seconds'.format(encode_time))
|
||||
print('Fast Decode: {}'.format(h(full_lc_dec)))
|
||||
print('Fast Decode Time: {} seconds'.format(lc_decode_time))
|
||||
|
||||
# Embedded LC
|
||||
t0 = time()
|
||||
emblc = encode_emblc(lc)
|
||||
t1 = time()
|
||||
encode_time = t1 -t0
|
||||
|
||||
t0 = time()
|
||||
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)
|
||||
decemblc = decode_emblc(emblc[0], emblc[1], emblc[2], emblc[3])
|
||||
t1 = time()
|
||||
decode_time = t1-t0
|
||||
decode_time = t1 -t0
|
||||
|
||||
print('\nEMBEDDED LC:')
|
||||
print('Encoded Embedded LC: Burst B:{}, Burst C:{}, Burst D:{}, Burst E:{}'.format(h(emblc[0].tobytes()), h(emblc[1].tobytes()), h(emblc[2].tobytes()), h(emblc[3].tobytes())))
|
||||
print('Endoder Time:', encode_time)
|
||||
print('Decoded Embedded LC:', h(decemblc))
|
||||
print('Decoder Time:', decode_time)
|
||||
|
||||
|
||||
print('VALIDATION ROUTINE:')
|
||||
print()
|
||||
print('ENCODER TEST:')
|
||||
print('Original Data: {}, {} bytes'.format(h(orig_data), len(orig_data)))
|
||||
print('Encoding time: {} seconds'.format(encode_time))
|
||||
print('Encoded data: {}, {} bits'.format(enc_data, len(enc_data)))
|
||||
print()
|
||||
print('DECODER TEST:')
|
||||
print('Encoded data: {}, {} bytes'.format(h(dec_data), len(dec_data)))
|
||||
print('Decoding Time: {} seconds'.format(t1-t0))
|
||||
if err_corrected:
|
||||
print('WARNING DATA COULD NOT BE CORRECTED')
|
||||
else:
|
||||
print('Decoded Data: {}, {} bytes'.format(h(ext_data), len(ext_data)))
|
||||
print()
|
||||
|
||||
print('ENCODED vs. DECODED:')
|
||||
print('enc:', enc_data)
|
||||
print('dec:', deint_data)
|
||||
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)
|
||||
|
21
dmr_decon.py
21
dmr_decon.py
@ -25,21 +25,12 @@ def to_bits(_string):
|
||||
_bits.frombytes(_string)
|
||||
return _bits
|
||||
|
||||
# Returns useable LC data - 9 bytes info + 3 bytes RS(12,9) ECC
|
||||
def lc_data_12(_data):
|
||||
return _data[4:12]+_data[16:27]+_data[31:42]+_data[46:57]+_data[61:72]+_data[76:87]+_data[91:102]+_data[106:117]+_data[121:132]
|
||||
|
||||
# Returns useable LC data - 9 bytes info, no ECC
|
||||
def lc_data_9(_data):
|
||||
return _data[4:12]+_data[16:27]+_data[31:42]+_data[46:57]+_data[61:72]+_data[76:87]+_data[91:100]
|
||||
|
||||
|
||||
def voice_head_term(_string):
|
||||
burst = to_bits(_string)
|
||||
info = burst[0:98] + burst[166:264]
|
||||
de_int_info = bptc.deinterleave_19696(info)
|
||||
slot_type = burst[98:108] + burst[156:166]
|
||||
lc = to_bytes(lc_data_9(de_int_info))
|
||||
lc = bptc.decode_full_lc(info).tobytes()
|
||||
cc = to_bytes(slot_type[0:4])
|
||||
dtype = to_bytes(slot_type[4:8])
|
||||
return (lc, cc, dtype)
|
||||
@ -116,35 +107,35 @@ if __name__ == '__main__':
|
||||
t0 = time()
|
||||
lc = voice(voice_b)
|
||||
t1 = time()
|
||||
print(lc[0], h(lc[1]), h(lc[2]), lc[3])
|
||||
print(lc[0], h(lc[1]), h(lc[2]), h(lc[3].tobytes()))
|
||||
print(t1-t0, '\n')
|
||||
|
||||
print('Voice Burst C Validation:')
|
||||
t0 = time()
|
||||
lc = voice(voice_c)
|
||||
t1 = time()
|
||||
print(lc[0], h(lc[1]), h(lc[2]), lc[3])
|
||||
print(lc[0], h(lc[1]), h(lc[2]), h(lc[3].tobytes()))
|
||||
print(t1-t0, '\n')
|
||||
|
||||
print('Voice Burst D Validation:')
|
||||
t0 = time()
|
||||
lc = voice(voice_d)
|
||||
t1 = time()
|
||||
print(lc[0], h(lc[1]), h(lc[2]), lc[3])
|
||||
print(lc[0], h(lc[1]), h(lc[2]), h(lc[3].tobytes()))
|
||||
print(t1-t0, '\n')
|
||||
|
||||
print('Voice Burst E Validation:')
|
||||
t0 = time()
|
||||
lc = voice(voice_e)
|
||||
t1 = time()
|
||||
print(lc[0], h(lc[1]), h(lc[2]), lc[3])
|
||||
print(lc[0], h(lc[1]), h(lc[2]), h(lc[3].tobytes()))
|
||||
print(t1-t0, '\n')
|
||||
|
||||
print('Voice Burst F Validation:')
|
||||
t0 = time()
|
||||
lc = voice(voice_f)
|
||||
t1 = time()
|
||||
print(lc[0], h(lc[1]), h(lc[2]), lc[3])
|
||||
print(lc[0], h(lc[1]), h(lc[2]), h(lc[3].tobytes()))
|
||||
print(t1-t0, '\n')
|
||||
|
||||
print('Terminator Validation:')
|
||||
|
Loading…
Reference in New Issue
Block a user