Initial commit
This commit is contained in:
commit
8c7c59e747
|
@ -0,0 +1,2 @@
|
|||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
|
@ -0,0 +1 @@
|
|||
name = "dmr_utils"
|
|
@ -0,0 +1,43 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
###############################################################################
|
||||
|
||||
|
||||
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
||||
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||
__copyright__ = 'Copyright (c) 2016-2018 Cortney T. Buffington, N0MJS and the K0USY Group'
|
||||
__credits__ = 'DSD'
|
||||
__license__ = 'GNU GPLv3'
|
||||
__maintainer__ = 'Cort Buffington, N0MJS'
|
||||
__email__ = 'n0mjs@me.com'
|
||||
|
||||
inter_X = (
|
||||
23, 5, 10, 3, 22, 4, 9, 2, 21, 3, 8, 1, 20, 2, 7, 0, 19, 1, 6, 13, 18, 0, 5, 12,
|
||||
17, 22, 4, 11, 16, 21, 3, 10, 15, 20, 2, 9, 14, 19, 1, 8, 13, 18, 0, 7, 12, 17, 10, 6,
|
||||
11, 16, 9, 5, 10, 15, 8, 4, 9, 14, 7, 3, 8, 13, 6, 2, 7, 12, 5, 1, 6, 11, 4, 0
|
||||
)
|
||||
|
||||
inter_W = (
|
||||
0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 2, 0, 0, 1, 3, 0, 0, 1, 3,
|
||||
0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 1, 3, 0, 1, 2, 3,
|
||||
0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3
|
||||
)
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(inter_X[13])
|
|
@ -0,0 +1,277 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2017 Mike Zingman N4IRR
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
###############################################################################
|
||||
|
||||
'''
|
||||
'''
|
||||
from binascii import b2a_hex as ahex
|
||||
from bitarray import bitarray
|
||||
from bitstring import BitArray
|
||||
from bitstring import BitString
|
||||
|
||||
__author__ = 'Mike Zingman, N4IRR and Cortney T. Buffington, N0MJS'
|
||||
__copyright__ = 'Copyright (c) 2017 Mike Zingman N4IRR'
|
||||
__credits__ = 'Cortney T. Buffington, N0MJS; Colin Durbridge, G4EML, Steve Zingman, N4IRS; Jonathan Naylor, G4KLX; Hans Barthen, DL5DI; Torsten Shultze, DG1HT'
|
||||
__license__ = 'GNU GPLv3'
|
||||
__maintainer__ = 'Cort Buffington, N0MJS'
|
||||
__email__ = 'n0mjs@me.com'
|
||||
|
||||
##
|
||||
# DMR AMBE interleave schedule
|
||||
##
|
||||
rW = [
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 1,
|
||||
0, 1, 0, 1, 0, 2,
|
||||
0, 2, 0, 2, 0, 2,
|
||||
0, 2, 0, 2, 0, 2
|
||||
]
|
||||
|
||||
rX = [
|
||||
23, 10, 22, 9, 21, 8,
|
||||
20, 7, 19, 6, 18, 5,
|
||||
17, 4, 16, 3, 15, 2,
|
||||
14, 1, 13, 0, 12, 10,
|
||||
11, 9, 10, 8, 9, 7,
|
||||
8, 6, 7, 5, 6, 4
|
||||
]
|
||||
|
||||
rY = [
|
||||
0, 2, 0, 2, 0, 2,
|
||||
0, 2, 0, 3, 0, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3,
|
||||
1, 3, 1, 3, 1, 3
|
||||
]
|
||||
|
||||
rZ = [
|
||||
5, 3, 4, 2, 3, 1,
|
||||
2, 0, 1, 13, 0, 12,
|
||||
22, 11, 21, 10, 20, 9,
|
||||
19, 8, 18, 7, 17, 6,
|
||||
16, 5, 15, 4, 14, 3,
|
||||
13, 2, 12, 1, 11, 0
|
||||
]
|
||||
|
||||
|
||||
# This function calculates [23,12] Golay codewords.
|
||||
# The format of the returned longint is [checkbits(11),data(12)].
|
||||
def golay2312(cw):
|
||||
POLY = 0xAE3 #/* or use the other polynomial, 0xC75 */
|
||||
cw = cw & 0xfff # Strip off check bits and only use data
|
||||
c = cw #/* save original codeword */
|
||||
for i in range(1,13): #/* examine each data bit */
|
||||
if (cw & 1): #/* test data bit */
|
||||
cw = cw ^ POLY #/* XOR polynomial */
|
||||
cw = cw >> 1 #/* shift intermediate result */
|
||||
return((cw << 12) | c) #/* assemble codeword */
|
||||
|
||||
# This function checks the overall parity of codeword cw.
|
||||
# If parity is even, 0 is returned, else 1.
|
||||
def parity(cw):
|
||||
#/* XOR the bytes of the codeword */
|
||||
p = cw & 0xff
|
||||
p = p ^ ((cw >> 8) & 0xff)
|
||||
p = p ^ ((cw >> 16) & 0xff)
|
||||
|
||||
#/* XOR the halves of the intermediate result */
|
||||
p = p ^ (p >> 4)
|
||||
p = p ^ (p >> 2)
|
||||
p = p ^ (p >> 1)
|
||||
|
||||
#/* return the parity result */
|
||||
return(p & 1)
|
||||
|
||||
# Demodulate ambe frame (C1)
|
||||
# Frame is an array [4][24]
|
||||
def demodulateAmbe3600x2450(ambe_fr):
|
||||
pr = [0] * 115
|
||||
foo = 0
|
||||
|
||||
# create pseudo-random modulator
|
||||
for i in range(23, 11, -1):
|
||||
foo = foo << 1
|
||||
foo = foo | ambe_fr[0][i]
|
||||
pr[0] = (16 * foo)
|
||||
for i in range(1, 24):
|
||||
pr[i] = (173 * pr[i - 1]) + 13849 - (65536 * (((173 * pr[i - 1]) + 13849) // 65536))
|
||||
for i in range(1, 24):
|
||||
pr[i] = pr[i] // 32768
|
||||
|
||||
# demodulate ambe_fr with pr
|
||||
k = 1
|
||||
for j in range(22, -1, -1):
|
||||
ambe_fr[1][j] = ((ambe_fr[1][j]) ^ pr[k])
|
||||
k = k + 1
|
||||
return ambe_fr # Pass it back since there is no pass by reference
|
||||
|
||||
def eccAmbe3600x2450Data(ambe_fr):
|
||||
ambe = bitarray()
|
||||
|
||||
# just copy C0
|
||||
for j in range(23, 11, -1):
|
||||
ambe.append(ambe_fr[0][j])
|
||||
|
||||
# # ecc and copy C1
|
||||
# gin = 0
|
||||
# for j in range(23):
|
||||
# gin = (gin << 1) | ambe_fr[1][j]
|
||||
#
|
||||
# gout = BitArray(hex(golay2312(gin)))
|
||||
# for j in range(22, 10, -1):
|
||||
# ambe[bitIndex] = gout[j]
|
||||
# bitIndex += 1
|
||||
for j in range(22, 10, -1):
|
||||
ambe.append(ambe_fr[1][j])
|
||||
|
||||
# just copy C2
|
||||
for j in range(10, -1, -1):
|
||||
ambe.append(ambe_fr[2][j])
|
||||
|
||||
# just copy C3
|
||||
for j in range(13, -1, -1):
|
||||
ambe.append(ambe_fr[3][j])
|
||||
|
||||
return ambe
|
||||
|
||||
# Convert a 49 bit raw AMBE frame into a deinterleaved structure (ready for decode by AMBE3000)
|
||||
def convert49BitAmbeTo72BitFrames( ambe_d ):
|
||||
index = 0
|
||||
ambe_fr = [[None for x in range(24)] for y in range(4)]
|
||||
|
||||
#Place bits into the 4x24 frames. [bit0...bit23]
|
||||
#fr0: [P e10 e9 e8 e7 e6 e5 e4 e3 e2 e1 e0 11 10 9 8 7 6 5 4 3 2 1 0]
|
||||
#fr1: [e10 e9 e8 e7 e6 e5 e4 e3 e2 e1 e0 23 22 21 20 19 18 17 16 15 14 13 12 xx]
|
||||
#fr2: [34 33 32 31 30 29 28 27 26 25 24 x x x x x x x x x x x x x]
|
||||
#fr3: [48 47 46 45 44 43 42 41 40 39 38 37 36 35 x x x x x x x x x x]
|
||||
|
||||
# ecc and copy C0: 12bits + 11ecc + 1 parity
|
||||
# First get the 12 bits that actually exist
|
||||
# Then calculate the golay codeword
|
||||
# And then add the parity bit to get the final 24 bit pattern
|
||||
|
||||
tmp = 0
|
||||
for i in range(11, -1, -1): #grab the 12 MSB
|
||||
tmp = (tmp << 1) | ambe_d[i]
|
||||
tmp = golay2312(tmp) #Generate the 23 bit result
|
||||
parityBit = parity(tmp)
|
||||
tmp = tmp | (parityBit << 23) #And create a full 24 bit value
|
||||
for i in range(23, -1, -1):
|
||||
ambe_fr[0][i] = (tmp & 1)
|
||||
tmp = tmp >> 1
|
||||
|
||||
# C1: 12 bits + 11ecc (no parity)
|
||||
tmp = 0
|
||||
for i in range(23,11, -1) : #grab the next 12 bits
|
||||
tmp = (tmp << 1) | ambe_d[i]
|
||||
tmp = golay2312(tmp) #Generate the 23 bit result
|
||||
for j in range(22, -1, -1):
|
||||
ambe_fr[1][j] = (tmp & 1)
|
||||
tmp = tmp >> 1;
|
||||
|
||||
#C2: 11 bits (no ecc)
|
||||
for j in range(10, -1, -1):
|
||||
ambe_fr[2][j] = ambe_d[34 - j]
|
||||
|
||||
#C3: 14 bits (no ecc)
|
||||
for j in range(13, -1, -1):
|
||||
ambe_fr[3][j] = ambe_d[48 - j];
|
||||
|
||||
return ambe_fr
|
||||
|
||||
def interleave(ambe_fr):
|
||||
bitIndex = 0
|
||||
w = 0
|
||||
x = 0
|
||||
y = 0
|
||||
z = 0
|
||||
data = bytearray(9)
|
||||
for i in range(36):
|
||||
bit1 = ambe_fr[rW[w]][rX[x]] # bit 1
|
||||
bit0 = ambe_fr[rY[y]][rZ[z]] # bit 0
|
||||
|
||||
|
||||
data[bitIndex // 8] = ((data[bitIndex // 8] << 1) & 0xfe) | (1 if (bit1 == 1) else 0)
|
||||
bitIndex += 1
|
||||
|
||||
data[bitIndex // 8] = ((data[bitIndex // 8] << 1) & 0xfe) | (1 if (bit0 == 1) else 0)
|
||||
bitIndex += 1
|
||||
|
||||
w += 1
|
||||
x += 1
|
||||
y += 1
|
||||
z += 1
|
||||
return data
|
||||
|
||||
def deinterleave(data):
|
||||
|
||||
ambe_fr = [[None for x in range(24)] for y in range(4)]
|
||||
|
||||
bitIndex = 0
|
||||
w = 0
|
||||
x = 0
|
||||
y = 0
|
||||
z = 0
|
||||
for i in range(36):
|
||||
bit1 = 1 if data[bitIndex] else 0
|
||||
bitIndex += 1
|
||||
|
||||
bit0 = 1 if data[bitIndex] else 0
|
||||
bitIndex += 1
|
||||
|
||||
ambe_fr[rW[w]][rX[x]] = bit1; # bit 1
|
||||
ambe_fr[rY[y]][rZ[z]] = bit0; # bit 0
|
||||
|
||||
w += 1
|
||||
x += 1
|
||||
y += 1
|
||||
z += 1
|
||||
|
||||
return ambe_fr
|
||||
|
||||
def convert72BitTo49BitAMBE( ambe72 ):
|
||||
ambe_fr = deinterleave(ambe72) # take 72 bit ambe and lay it out in C0-C3
|
||||
ambe_fr = demodulateAmbe3600x2450(ambe_fr) # demodulate C1
|
||||
ambe49 = eccAmbe3600x2450Data(ambe_fr) # pick out the 49 bits of raw ambe
|
||||
return ambe49
|
||||
|
||||
def convert49BitTo72BitAMBE( ambe49 ):
|
||||
ambe_fr = convert49BitAmbeTo72BitFrames(ambe49) # take raw ambe 49 + ecc and place it into C0-C3
|
||||
ambe_fr = demodulateAmbe3600x2450(ambe_fr) # demodulate C1
|
||||
ambe72 = interleave(ambe_fr); # Re-interleave it, returning 72 bits
|
||||
return ambe72
|
||||
|
||||
def testit():
|
||||
ambe72 = BitArray('0xACAA40200044408080') #silence frame
|
||||
print('ambe72=',ambe72)
|
||||
|
||||
ambe49 = convert72BitTo49BitAMBE(ambe72)
|
||||
print('ambe49=',ahex(ambe49.tobytes()))
|
||||
|
||||
ambe72 = convert49BitTo72BitAMBE(ambe49)
|
||||
print('ambe72=',ahex(ambe72))
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Used to execute the module directly to run built-in tests
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
testit()
|
|
@ -0,0 +1,263 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
# Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
###############################################################################
|
||||
|
||||
|
||||
from bitarray import bitarray
|
||||
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'
|
||||
__copyright__ = 'Copyright (c) 2016-2018 Cortney T. Buffington, N0MJS and the K0USY Group'
|
||||
__credits__ = 'Jonathan Naylor, G4KLX; Ian Wraith'
|
||||
__license__ = 'GNU GPLv3'
|
||||
__maintainer__ = 'Cort Buffington, N0MJS'
|
||||
__email__ = 'n0mjs@me.com'
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Interleaver Index
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
INDEX_181 = (
|
||||
0, 181, 166, 151, 136, 121, 106, 91, 76, 61, 46, 31, 16, 1, 182, 167, 152, 137,
|
||||
122, 107, 92, 77, 62, 47, 32, 17, 2, 183, 168, 153, 138, 123, 108, 93, 78, 63,
|
||||
48, 33, 18, 3, 184, 169, 154, 139, 124, 109, 94, 79, 64, 49, 34, 19, 4, 185, 170,
|
||||
155, 140, 125, 110, 95, 80, 65, 50, 35, 20, 5, 186, 171, 156, 141, 126, 111, 96,
|
||||
81, 66, 51, 36, 21, 6, 187, 172, 157, 142, 127, 112, 97, 82, 67, 52, 37, 22, 7,
|
||||
188, 173, 158, 143, 128, 113, 98, 83, 68, 53, 38, 23, 8, 189, 174, 159, 144, 129,
|
||||
114, 99, 84, 69, 54, 39, 24, 9, 190, 175, 160, 145, 130, 115, 100, 85, 70, 55, 40,
|
||||
25, 10, 191, 176, 161, 146, 131, 116, 101, 86, 71, 56, 41, 26, 11, 192, 177, 162,
|
||||
147, 132, 117, 102, 87, 72, 57, 42, 27, 12, 193, 178, 163, 148, 133, 118, 103, 88,
|
||||
73, 58, 43, 28, 13, 194, 179, 164, 149, 134, 119, 104, 89, 74, 59, 44, 29, 14,
|
||||
195, 180, 165, 150, 135, 120, 105, 90, 75, 60, 45, 30, 15)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# BPTC(196,96) Decoding Routings
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
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
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
def interleave_19696(_data):
|
||||
inter = bitarray(196, endian='big')
|
||||
for index in range(196):
|
||||
inter[INDEX_181[index]] = _data[index] # the real math is slower: deint[index] = _data[(index * 181) % 196]
|
||||
return inter
|
||||
|
||||
# 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_19696(_data):
|
||||
# Create a bitarray from the 4 bytes of LC data (includes RS1293 ECC)
|
||||
_bdata = bitarray(endian='big')
|
||||
_bdata.frombytes(_data)
|
||||
|
||||
# Insert R0-R3 bits
|
||||
for i in range(4):
|
||||
_bdata.insert(0, 0)
|
||||
|
||||
# Get row hamming 15,11,3 and append. +1 is to account for R3 that makes an even 196bit string
|
||||
for index in range(9):
|
||||
spos = (index*15) + 1
|
||||
epos= spos + 11
|
||||
_rowp = hamming.enc_15113(_bdata[spos:epos])
|
||||
for pbit in range(4):
|
||||
_bdata.insert(epos+pbit,_rowp[pbit])
|
||||
|
||||
# Get column hamming 13,9,3 and append. +1 is to account for R3 that makes an even 196bit string
|
||||
# Pad out the bitarray to a full 196 bits. Can't insert into 'columns'
|
||||
for i in range(60):
|
||||
_bdata.append(0)
|
||||
|
||||
column = bitarray(9, endian='big') # Temporary bitarray to hold column data
|
||||
for col in range(15):
|
||||
spos = col + 1
|
||||
for index in range(9):
|
||||
column[index] = _bdata[spos]
|
||||
spos += 15
|
||||
_colp = hamming.enc_1393(column)
|
||||
|
||||
# Insert bits into matrix...
|
||||
cpar = 136 + col # Starting location in the matrix for column bits
|
||||
for pbit in range(4):
|
||||
_bdata[cpar] = _colp[pbit]
|
||||
cpar += 15
|
||||
|
||||
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):
|
||||
full_lc = _lc + rs129.lc_terminator_encode(_lc)
|
||||
full_lc = encode_19696(full_lc)
|
||||
full_lc = interleave_19696(full_lc)
|
||||
return full_lc
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# BPTC Embedded LC Decoding Routines
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
def decode_emblc(_elc):
|
||||
|
||||
_binlc = bitarray(endian='big')
|
||||
_binlc.extend([_elc[0],_elc[8], _elc[16],_elc[24],_elc[32],_elc[40],_elc[48],_elc[56],_elc[64],_elc[72] ,_elc[80]])
|
||||
_binlc.extend([_elc[1],_elc[9], _elc[17],_elc[25],_elc[33],_elc[41],_elc[49],_elc[57],_elc[65],_elc[73] ,_elc[81]])
|
||||
_binlc.extend([_elc[2],_elc[10],_elc[18],_elc[26],_elc[34],_elc[42],_elc[50],_elc[58],_elc[66],_elc[74]])
|
||||
_binlc.extend([_elc[3],_elc[11],_elc[19],_elc[27],_elc[35],_elc[43],_elc[51],_elc[59],_elc[67],_elc[75]])
|
||||
_binlc.extend([_elc[4],_elc[12],_elc[20],_elc[28],_elc[36],_elc[44],_elc[52],_elc[60],_elc[68],_elc[76]])
|
||||
_binlc.extend([_elc[5],_elc[13],_elc[21],_elc[29],_elc[37],_elc[45],_elc[53],_elc[61],_elc[69],_elc[77]])
|
||||
_binlc.extend([_elc[6],_elc[14],_elc[22],_elc[30],_elc[38],_elc[46],_elc[54],_elc[62],_elc[70],_elc[78]])
|
||||
|
||||
return(_binlc.tobytes())
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# 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):
|
||||
|
||||
# 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,_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 range(0,112,16):
|
||||
for hindex,hbit in zip(range(index+11,index+16), hamming.enc_16114(_binlc[index:index+11])):
|
||||
_binlc.insert(hindex,hbit)
|
||||
|
||||
# Insert the column parity bits at the right location in the matrix
|
||||
for index in range(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])
|
||||
|
||||
# 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]])
|
||||
|
||||
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({1: emblc_b, 2: emblc_c, 3: emblc_d, 4: emblc_e})
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Used to execute the module directly to run built-in tests
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
from binascii import b2a_hex as ahex
|
||||
from time import time
|
||||
|
||||
# Validation Example
|
||||
|
||||
voice_h = b'\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'
|
||||
voice_hb = bitarray(endian='big')
|
||||
voice_hb.frombytes(voice_h)
|
||||
voice_hb = voice_hb[0:98] + voice_hb[166:264]
|
||||
|
||||
# Header LC -- Terminator similar
|
||||
lc = b'\x00\x10\x20\x00\x0c\x30\x2f\x9b\xe5' # \xda\xd4\x5a
|
||||
t0 = time()
|
||||
full_lc_encode = encode_header_lc(lc)
|
||||
t1 = time()
|
||||
encode_time = t1-t0
|
||||
|
||||
t0 = time()
|
||||
full_lc_dec = decode_full_lc(full_lc_encode)
|
||||
t1 = time()
|
||||
decode_time = t1-t0
|
||||
|
||||
print('VALIDATION ROUTINES:')
|
||||
print('Orig Data: {}, {} bytes'.format(ahex(lc), len(lc)))
|
||||
print('Orig Encoded: {}, {} bytes'.format(ahex(voice_hb.tobytes()), len(voice_hb.tobytes())))
|
||||
print()
|
||||
print('BPTC(196,96):')
|
||||
print('Encoded data: {}, {} bytes'.format(ahex(full_lc_encode.tobytes()), len(full_lc_encode.tobytes())))
|
||||
print('Encoding time: {} seconds'.format(encode_time))
|
||||
print('Decoded data: {}'.format(ahex(full_lc_dec.tobytes())))
|
||||
print('Decode Time: {} seconds'.format(decode_time))
|
||||
|
||||
# Embedded LC
|
||||
t0 = time()
|
||||
emblc = encode_emblc(lc)
|
||||
t1 = time()
|
||||
encode_time = t1 -t0
|
||||
|
||||
t0 = time()
|
||||
decemblc = decode_emblc(emblc[1] + emblc[2] + emblc[3] + emblc[4])
|
||||
t1 = time()
|
||||
decode_time = t1 -t0
|
||||
|
||||
print('\nEMBEDDED LC:')
|
||||
print('Encoded Data: Burst B:{} Burst C:{} Burst D:{} Burst E:{}'.format(ahex(emblc[1].tobytes()), ahex(emblc[2].tobytes()), ahex(emblc[3].tobytes()), ahex(emblc[4].tobytes())))
|
||||
print('Endoding Time: {}'.format(encode_time))
|
||||
print('Decoded data: {}'.format(ahex(decemblc)))
|
||||
print('Decoding Time: {}'.format(decode_time))
|
|
@ -0,0 +1,107 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
###############################################################################
|
||||
|
||||
|
||||
from bitarray import bitarray
|
||||
|
||||
|
||||
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||
__copyright__ = 'Copyright (c) 2016-2018 Cortney T. Buffington, N0MJS and the K0USY Group'
|
||||
__credits__ = ''
|
||||
__license__ = 'GNU GPLv3'
|
||||
__maintainer__ = 'Cort Buffington, N0MJS'
|
||||
__email__ = 'n0mjs@me.com'
|
||||
|
||||
# Slot Type Data types
|
||||
DMR_SLT_VHEAD = b'\x01'
|
||||
DMR_SLT_VTERM = b'\x02'
|
||||
|
||||
# Sync patterns used for LC and Voice Burst A packets
|
||||
BS_VOICE_SYNC = bitarray()
|
||||
BS_DATA_SYNC = bitarray()
|
||||
BS_VOICE_SYNC.frombytes(b'\x75\x5F\xD7\xDF\x75\xF7')
|
||||
BS_DATA_SYNC.frombytes(b'\xDF\xF5\x7D\x75\xDF\x5D')
|
||||
|
||||
SYNC = {
|
||||
'BS_VOICE': BS_VOICE_SYNC,
|
||||
'BS_DATA': BS_DATA_SYNC
|
||||
}
|
||||
|
||||
# LC Options - Use for Group Voice
|
||||
LC_OPT = b'\x00\x00\x20'
|
||||
|
||||
# Precomputed EMB values, where CC always = 1, and PI always = 0
|
||||
EMB = {
|
||||
'BURST_B': bitarray('0001001110010001'),
|
||||
'BURST_C': bitarray('0001011101110100'),
|
||||
'BURST_D': bitarray('0001011101110100'),
|
||||
'BURST_E': bitarray('0001010100000111'),
|
||||
'BURST_F': bitarray('0001000111100010')
|
||||
}
|
||||
|
||||
# Precomputed Slot Type values where CC always = 1
|
||||
SLOT_TYPE = {
|
||||
'PI_HEAD': bitarray('00010000001101100111'),
|
||||
'VOICE_LC_HEAD': bitarray('00010001101110001100'),
|
||||
'VOICE_LC_TERM': bitarray('00010010101001011001'),
|
||||
'CSBK': bitarray('00010011001010110010'),
|
||||
'MBC_HEAD': bitarray('00010100100111110000'),
|
||||
'MBC_CONT': bitarray('00010101000100011011'),
|
||||
'DATA_HEAD': bitarray('00010110000011001110'),
|
||||
'1/2_DATA': bitarray('00010111100000100101'),
|
||||
'3/4_DATA': bitarray('00011000111010100001'),
|
||||
'IDLE': bitarray('00011001011001001010'),
|
||||
'1/1_DATA': bitarray('00011010011110011111'),
|
||||
'RES_1': bitarray('00011011111101110100'),
|
||||
'RES_2': bitarray('00011100010000110110'),
|
||||
'RES_3': bitarray('00011101110011011101'),
|
||||
'RES_4': bitarray('00011110110100001000'),
|
||||
'RES_5': bitarray('00011111010111100011')
|
||||
}
|
||||
|
||||
# LC infor for first 3 Bytes:
|
||||
# Byte 1: PF (1),Res(1),FLCO(6) -- Byte 2: FID(8) -- Byte 3: Service Options(8)
|
||||
LC_VOICE = {
|
||||
'FLCO-GRP': bitarray('00000000'),
|
||||
'FLCO-USR': bitarray('00000011'),
|
||||
'FID-GENC': bitarray('00000000'),
|
||||
'FID-MOTO': bitarray('00010000'),
|
||||
'SVC-OVCM': bitarray('00100000'),
|
||||
'SVC-NONE': bitarray('00000000')
|
||||
}
|
||||
|
||||
'''
|
||||
EMB: CC(4b), PI(1b), LCSS(2b), EMB Parity(9b - QR 16,7,5)
|
||||
Slot Type: CC(4b), DataType(4), Slot Type Parity(12b - )
|
||||
|
||||
'''
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Used to execute the module directly to run built-in tests
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
from pprint import pprint
|
||||
|
||||
pprint(SYNC)
|
||||
pprint(EMB)
|
||||
pprint(SLOT_TYPE)
|
||||
print(LC_OPT)
|
|
@ -0,0 +1,52 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
###############################################################################
|
||||
|
||||
|
||||
from bitarray import bitarray
|
||||
|
||||
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
||||
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||
__copyright__ = 'Copyright (c) 2016-2018 Cortney T. Buffington, N0MJS and the K0USY Group'
|
||||
__credits__ = 'Jonathan Naylor, G4KLX'
|
||||
__license__ = 'GNU GPLv3'
|
||||
__maintainer__ = 'Cort Buffington, N0MJS'
|
||||
__email__ = 'n0mjs@me.com'
|
||||
|
||||
|
||||
def csum5(_data):
|
||||
accum = 0
|
||||
assert len(_data) == 9, 'csum5 expected 9 bytes of data and got something else'
|
||||
|
||||
for i in range(9):
|
||||
accum += _data[i]
|
||||
accum = bytes([accum % 31])
|
||||
csum = bitarray()
|
||||
csum.frombytes(accum)
|
||||
del csum[0:3]
|
||||
|
||||
return csum
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
message = b'\x00\x10\x20\x00\x0c\x30\x2f\x9b\xe5'
|
||||
|
||||
result = csum5(message)
|
||||
print(result, type(result))
|
|
@ -0,0 +1,184 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
###############################################################################
|
||||
|
||||
|
||||
|
||||
from bitarray import bitarray
|
||||
import bptc
|
||||
|
||||
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
||||
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||
__copyright__ = 'Copyright (c) 2016-2018 Cortney T. Buffington, N0MJS and the K0USY Group'
|
||||
__credits__ = 'Jonathan Naylor, G4KLX; Ian Wraith'
|
||||
__license__ = 'GNU GPLv3'
|
||||
__maintainer__ = 'Cort Buffington, N0MJS'
|
||||
__email__ = 'n0mjs@me.com'
|
||||
|
||||
def to_bits(_string):
|
||||
_bits = bitarray(endian='big')
|
||||
_bits.frombytes(_string)
|
||||
return _bits
|
||||
|
||||
|
||||
def voice_head_term(_string):
|
||||
burst = to_bits(_string)
|
||||
info = burst[0:98] + burst[166:264]
|
||||
slot_type = burst[98:108] + burst[156:166]
|
||||
sync = burst[108:156]
|
||||
lc = bptc.decode_full_lc(info).tobytes()
|
||||
cc = to_bytes(slot_type[0:4])
|
||||
dtype = to_bytes(slot_type[4:8])
|
||||
return {'LC': lc, 'CC': cc, 'DTYPE': dtype, 'SYNC': sync}
|
||||
|
||||
|
||||
def voice_sync(_string):
|
||||
burst = to_bits(_string)
|
||||
ambe = [0,0,0]
|
||||
ambe[0] = burst[0:72]
|
||||
ambe[1] = burst[72:108] + burst[156:192]
|
||||
ambe[2] = burst[192:264]
|
||||
sync = burst[108:156]
|
||||
return {'AMBE': ambe, 'SYNC': sync}
|
||||
|
||||
|
||||
def voice(_string):
|
||||
burst = to_bits(_string)
|
||||
ambe = [0,0,0]
|
||||
ambe[0] = burst[0:72]
|
||||
ambe[1] = burst[72:108] + burst[156:192]
|
||||
ambe[2] = burst[192:264]
|
||||
emb = burst[108:116] + burst[148:156]
|
||||
embed = burst[116:148]
|
||||
cc = (to_bytes(emb[0:4]))
|
||||
lcss = (to_bytes(emb[5:7]))
|
||||
return {'AMBE': ambe, 'CC': cc, 'LCSS': lcss, 'EMBED': embed}
|
||||
|
||||
|
||||
def to_bytes(_bits):
|
||||
add_bits = 8 - (len(_bits) % 8)
|
||||
if add_bits < 8:
|
||||
for bit in range(add_bits):
|
||||
_bits.insert(0,0)
|
||||
_string = _bits.tobytes()
|
||||
return _string
|
||||
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Used to execute the module directly to run built-in tests
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
from binascii import b2a_hex as ahex
|
||||
from time import time
|
||||
|
||||
# SAMPLE, KNOWN GOOD DMR BURSTS
|
||||
data_head = b'\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'
|
||||
voice_a = b'\xb9\xe8\x81\x52\x61\x73\x00\x2a\x6b\xb9\xe8\x81\x52\x67\x55\xfd\x7d\xf7\x5f\x71\x73\x00\x2a\x6b\xb9\xe8\x81\x52\x61\x73\x00\x2a\x6a'
|
||||
voice_b = b'\xb9\xe8\x81\x52\x61\x73\x00\x2a\x6b\xb9\xe8\x81\x52\x61\x34\xe0\xf0\x60\x69\x11\x73\x00\x2a\x6b\xb9\xe8\x81\x52\x61\x73\x00\x2a\x6a'
|
||||
voice_c = b'\xb9\xe8\x81\x52\x61\x73\x00\x2a\x6b\xb9\xe8\x81\x52\x61\x71\x71\x10\x04\x77\x41\x73\x00\x2a\x6b\xb9\xe8\x81\x52\x61\x73\x00\x2a\x6a'
|
||||
voice_d = b'\xb9\xe8\x81\x52\x61\x73\x00\x2a\x6b\x95\x4b\xe6\x50\x01\x70\xc0\x31\x81\xb7\x43\x10\xb0\x07\x77\xa6\xc6\xcb\x53\x73\x27\x89\x48\x3a'
|
||||
voice_e = b'\x86\x5a\xe7\x61\x75\x55\xb5\x06\x01\xb7\x58\xe6\x65\x11\x51\x75\xa0\xf4\xe0\x71\x24\x81\x50\x01\xff\xf5\xa3\x37\x70\x61\x28\xa7\xca'
|
||||
voice_f = b'\xee\xe7\x81\x75\x74\x61\x4d\xf2\xff\xcc\xf4\xa0\x55\x11\x10\x00\x00\x00\x0e\x24\x30\x59\xe7\xf9\xe9\x08\xa0\x75\x62\x02\xcc\xd6\x22'
|
||||
voice_term = b'\x2b\x0f\x04\xc4\x1f\x34\x2d\xa8\x0d\x80\x7d\xe1\x04\xad\xff\x57\xd7\x5d\xf5\xd9\x65\x01\x2d\x18\x77\xd2\x03\xc0\x37\x88\xdf\x95\xd1'
|
||||
|
||||
embed_lc = bitarray()
|
||||
|
||||
print('DMR PACKET DECODER VALIDATION\n')
|
||||
print('Header:')
|
||||
t0 = time()
|
||||
lc = voice_head_term(data_head)
|
||||
t1 = time()
|
||||
print('LC: OPT-{} SRC-{} DST-{}, SLOT TYPE: CC-{} DTYPE-{}'.format(ahex(lc['LC'][0:3]),ahex(lc['LC'][3:6]),ahex(lc['LC'][6:9]),ahex(lc['CC']),ahex(lc['DTYPE'])))
|
||||
print('Decode Time: {}\n'.format(t1-t0))
|
||||
|
||||
print('Voice Burst A:')
|
||||
t0 = time()
|
||||
pkt = voice_sync(voice_a)
|
||||
t1 = time()
|
||||
print('VOICE SYNC: {}'.format(ahex(lc['SYNC'].tobytes())))
|
||||
print('AMBE 0: {}, {}'.format(pkt['AMBE'][0], len(pkt['AMBE'][0])))
|
||||
print('AMBE 1: {}, {}'.format(pkt['AMBE'][1], len(pkt['AMBE'][1])))
|
||||
print('AMBE 2: {}, {}'.format(pkt['AMBE'][1], len(pkt['AMBE'][2])))
|
||||
print(t1-t0, '\n')
|
||||
|
||||
print('Voice Burst B:')
|
||||
t0 = time()
|
||||
pkt = voice(voice_b)
|
||||
embed_lc += pkt['EMBED']
|
||||
t1 = time()
|
||||
print('EMB: CC-{} LCSS-{}, EMBEDDED LC: {}'.format(ahex(pkt['CC']), ahex(pkt['LCSS']), ahex(pkt['EMBED'].tobytes())))
|
||||
print('AMBE 0: {}, {}'.format(pkt['AMBE'][0], len(pkt['AMBE'][0])))
|
||||
print('AMBE 1: {}, {}'.format(pkt['AMBE'][1], len(pkt['AMBE'][1])))
|
||||
print('AMBE 2: {}, {}'.format(pkt['AMBE'][1], len(pkt['AMBE'][2])))
|
||||
print(t1-t0, '\n')
|
||||
|
||||
print('Voice Burst C:')
|
||||
t0 = time()
|
||||
pkt = voice(voice_c)
|
||||
embed_lc += pkt['EMBED']
|
||||
t1 = time()
|
||||
print('EMB: CC-{} LCSS-{}, EMBEDDED LC: {}'.format(ahex(pkt['CC']), ahex(pkt['LCSS']), ahex(pkt['EMBED'].tobytes())))
|
||||
print('AMBE 0: {}, {}'.format(pkt['AMBE'][0], len(pkt['AMBE'][0])))
|
||||
print('AMBE 1: {}, {}'.format(pkt['AMBE'][1], len(pkt['AMBE'][1])))
|
||||
print('AMBE 2: {}, {}'.format(pkt['AMBE'][1], len(pkt['AMBE'][2])))
|
||||
print(t1-t0, '\n')
|
||||
|
||||
print('Voice Burst D:')
|
||||
t0 = time()
|
||||
pkt = voice(voice_d)
|
||||
embed_lc += pkt['EMBED']
|
||||
t1 = time()
|
||||
print('EMB: CC-{} LCSS-{}, EMBEDDED LC: {}'.format(ahex(pkt['CC']), ahex(pkt['LCSS']), ahex(pkt['EMBED'].tobytes())))
|
||||
print('AMBE 0: {}, {}'.format(pkt['AMBE'][0], len(pkt['AMBE'][0])))
|
||||
print('AMBE 1: {}, {}'.format(pkt['AMBE'][1], len(pkt['AMBE'][1])))
|
||||
print('AMBE 2: {}, {}'.format(pkt['AMBE'][1], len(pkt['AMBE'][2])))
|
||||
print(t1-t0, '\n')
|
||||
|
||||
print('Voice Burst E:')
|
||||
t0 = time()
|
||||
pkt = voice(voice_e)
|
||||
embed_lc += pkt['EMBED']
|
||||
embed_lc = bptc.decode_emblc(embed_lc)
|
||||
t1 = time()
|
||||
print('EMB: CC-{} LCSS-{}, EMBEDDED LC: {}'.format(ahex(pkt['CC']), ahex(pkt['LCSS']), ahex(pkt['EMBED'].tobytes())))
|
||||
print('COMPLETE EMBEDDED LC: {}'.format(ahex(embed_lc)))
|
||||
print('AMBE 0: {}, {}'.format(pkt['AMBE'][0], len(pkt['AMBE'][0])))
|
||||
print('AMBE 1: {}, {}'.format(pkt['AMBE'][1], len(pkt['AMBE'][1])))
|
||||
print('AMBE 2: {}, {}'.format(pkt['AMBE'][1], len(pkt['AMBE'][2])))
|
||||
print(t1-t0, '\n')
|
||||
|
||||
print('Voice Burst F:')
|
||||
t0 = time()
|
||||
pkt = voice(voice_f)
|
||||
t1 = time()
|
||||
print('EMB: CC-{} LCSS-{}, EMBEDDED LC: {}'.format(ahex(pkt['CC']), ahex(pkt['LCSS']), ahex(pkt['EMBED'].tobytes())))
|
||||
print('AMBE 0: {}, {}'.format(pkt['AMBE'][0], len(pkt['AMBE'][0])))
|
||||
print('AMBE 1: {}, {}'.format(pkt['AMBE'][1], len(pkt['AMBE'][1])))
|
||||
print('AMBE 2: {}, {}'.format(pkt['AMBE'][1], len(pkt['AMBE'][2])))
|
||||
print(t1-t0, '\n')
|
||||
|
||||
print('Terminator:')
|
||||
t0 = time()
|
||||
lc = voice_head_term(voice_term)
|
||||
t1 = time()
|
||||
print('LC: OPT-{} SRC-{} DST-{} SLOT TYPE: CC-{} DTYPE-{}'.format(ahex(lc['LC'][0:3]),ahex(lc['LC'][3:6]),ahex(lc['LC'][6:9]),ahex(lc['CC']),ahex(lc['DTYPE'])))
|
||||
print('Decode Time: {}\n'.format(t1-t0))
|
|
@ -0,0 +1,38 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
###############################################################################
|
||||
|
||||
|
||||
from bitarray import bitarray
|
||||
import const
|
||||
|
||||
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
||||
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||
__copyright__ = 'Copyright (c) 2016-2018 Cortney T. Buffington, N0MJS and the K0USY Group'
|
||||
__license__ = 'GNU GPLv3'
|
||||
__maintainer__ = 'Cort Buffington, N0MJS'
|
||||
__email__ = 'n0mjs@me.com'
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Used to execute the module directly to run built-in tests
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
pass
|
|
@ -0,0 +1,99 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
###############################################################################
|
||||
|
||||
|
||||
from bitarray import bitarray
|
||||
from binascii import b2a_hex as ahex
|
||||
|
||||
from golay_tables import *
|
||||
|
||||
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
||||
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||
__copyright__ = 'Copyright (c) 2016-2018 Cortney T. Buffington, N0MJS and the K0USY Group'
|
||||
__credits__ = 'Jonathan Naylor, G4KLX who many parts of this were thankfully borrowed from'
|
||||
__license__ = 'GNU GPLv3'
|
||||
__maintainer__ = 'Cort Buffington, N0MJS'
|
||||
__email__ = 'n0mjs@me.com'
|
||||
|
||||
|
||||
X22 = 0x00400000 # vector representation of X^22
|
||||
X18 = 0x00040000 # vector representation of X^18
|
||||
X11 = 0x00000800 # vector representation of X^11
|
||||
MASK12 = 0xfffff800 # auxiliary vector for testing
|
||||
MASK8 = 0xfffff800 # auxiliary vector for testing
|
||||
GENPOL = 0x00000c75 # generator polinomial, g(x)
|
||||
|
||||
# This routine currently uses hex strings of the precalculated codes.
|
||||
# This generates them from the integer table for (20,8,7)
|
||||
ENCSTR_2087 = [0 for x in range(256)]
|
||||
for value in range(256):
|
||||
ENCSTR_2087[value] = ENCODE_2087[value].to_bytes(2, 'big')
|
||||
|
||||
def get_synd_1987(_pattern):
|
||||
aux = X18
|
||||
if _pattern >= X11:
|
||||
while _pattern & MASK8:
|
||||
while not (aux & _pattern):
|
||||
aux = aux >> 1
|
||||
_pattern = _pattern ^ ((aux // X11) * GENPOL)
|
||||
return _pattern
|
||||
|
||||
def get_synd_23127(_pattern):
|
||||
aux = X22
|
||||
if _pattern >= X11:
|
||||
while _pattern & MASK12:
|
||||
while not (aux & _pattern):
|
||||
aux = aux >> 1
|
||||
_pattern = _pattern ^ ((aux // X11) * GENPOL)
|
||||
return _pattern
|
||||
|
||||
def decode_2087(_data):
|
||||
bin_data = int(ahex(_data), 16)
|
||||
syndrome = get_synd_1987(bin_data)
|
||||
error_pattern = DECODE_1987[syndrome]
|
||||
if error_pattern != 0x00:
|
||||
bin_data = bin_data ^ error_pattern
|
||||
return bin_data >> 12
|
||||
|
||||
def encode_2087(_data):
|
||||
byte = ord(_data)
|
||||
cksum = ENCODE_2087[byte]
|
||||
return ( byte << 12 | (cksum & 0xFF) << 4 | cksum >> 12)
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Used to execute the module directly to run built-in tests
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
from time import time
|
||||
|
||||
# For testing the code
|
||||
def print_hex(_list):
|
||||
print(('[{}]'.format(', '.join(hex(x) for x in _list))))
|
||||
|
||||
to_decode = b'\x01\x2a\x59'
|
||||
to_encode = b'\x12'
|
||||
|
||||
print((hex(decode_2087(to_decode))))
|
||||
|
||||
encoded = encode_2087(to_encode)
|
||||
print((hex(encoded)))
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,75 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
# Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
###############################################################################
|
||||
|
||||
|
||||
from bitarray import bitarray
|
||||
|
||||
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
||||
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||
__copyright__ = 'Copyright (c) 2016-2018 Cortney T. Buffington, N0MJS and the K0USY Group'
|
||||
__credits__ = 'Jonathan Naylor, G4KLX'
|
||||
__license__ = 'GNU GPLv3'
|
||||
__maintainer__ = 'Cort Buffington, N0MJS'
|
||||
__email__ = 'n0mjs@me.com'
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Hamming 15,11,3 routines
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# ENCODER- returns a bitarray object containing the hamming checksums
|
||||
def enc_15113(_data):
|
||||
csum = bitarray(4)
|
||||
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]
|
||||
csum[2] = _data[2] ^ _data[3] ^ _data[4] ^ _data[5] ^ _data[7] ^ _data[9] ^ _data[10]
|
||||
csum[3] = _data[0] ^ _data[1] ^ _data[2] ^ _data[4] ^ _data[6] ^ _data[7] ^ _data[10]
|
||||
return csum
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Hamming 13,9,3 routines
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# ENCODER - returns a bitarray object containing the hamming checksums
|
||||
def enc_1393(_data):
|
||||
csum = bitarray(4)
|
||||
csum[0] = _data[0] ^ _data[1] ^ _data[3] ^ _data[5] ^ _data[6]
|
||||
csum[1] = _data[0] ^ _data[1] ^ _data[2] ^ _data[4] ^ _data[6] ^ _data[7]
|
||||
csum[2] = _data[0] ^ _data[1] ^ _data[2] ^ _data[3] ^ _data[5] ^ _data[7] ^ _data[8]
|
||||
csum[3] = _data[0] ^ _data[2] ^ _data[4] ^ _data[5] ^ _data[8]
|
||||
return csum
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Hamming 16,11,4 routines
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
# 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]
|
||||
csum[2] = _data[2] ^ _data[3] ^ _data[4] ^ _data[5] ^ _data[7] ^ _data[9] ^ _data[10]
|
||||
csum[3] = _data[0] ^ _data[1] ^ _data[2] ^ _data[4] ^ _data[6] ^ _data[7] ^ _data[10]
|
||||
csum[4] = _data[0] ^ _data[2] ^ _data[5] ^ _data[6] ^ _data[8] ^ _data[9] ^ _data[10]
|
||||
return csum
|
|
@ -0,0 +1,120 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
# Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
###############################################################################
|
||||
|
||||
|
||||
|
||||
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
||||
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||
__copyright__ = 'Copyright (c) 2016-2018 Cortney T. Buffington, N0MJS and the K0USY Group'
|
||||
__credits__ = 'Jonathan Naylor, G4KLX who many parts of this were thankfully borrowed from'
|
||||
__license__ = 'GNU GPLv3'
|
||||
__maintainer__ = 'Cort Buffington, N0MJS'
|
||||
__email__ = 'n0mjs@me.com'
|
||||
|
||||
|
||||
ENCODE_1676 = (
|
||||
0x0000, 0x0273, 0x04E5, 0x0696, 0x09C9, 0x0BBA, 0x0D2C, 0x0F5F, 0x11E2, 0x1391, 0x1507, 0x1774,
|
||||
0x182B, 0x1A58, 0x1CCE, 0x1EBD, 0x21B7, 0x23C4, 0x2552, 0x2721, 0x287E, 0x2A0D, 0x2C9B, 0x2EE8,
|
||||
0x3055, 0x3226, 0x34B0, 0x36C3, 0x399C, 0x3BEF, 0x3D79, 0x3F0A, 0x411E, 0x436D, 0x45FB, 0x4788,
|
||||
0x48D7, 0x4AA4, 0x4C32, 0x4E41, 0x50FC, 0x528F, 0x5419, 0x566A, 0x5935, 0x5B46, 0x5DD0, 0x5FA3,
|
||||
0x60A9, 0x62DA, 0x644C, 0x663F, 0x6960, 0x6B13, 0x6D85, 0x6FF6, 0x714B, 0x7338, 0x75AE, 0x77DD,
|
||||
0x7882, 0x7AF1, 0x7C67, 0x7E14, 0x804F, 0x823C, 0x84AA, 0x86D9, 0x8986, 0x8BF5, 0x8D63, 0x8F10,
|
||||
0x91AD, 0x93DE, 0x9548, 0x973B, 0x9864, 0x9A17, 0x9C81, 0x9EF2, 0xA1F8, 0xA38B, 0xA51D, 0xA76E,
|
||||
0xA831, 0xAA42, 0xACD4, 0xAEA7, 0xB01A, 0xB269, 0xB4FF, 0xB68C, 0xB9D3, 0xBBA0, 0xBD36, 0xBF45,
|
||||
0xC151, 0xC322, 0xC5B4, 0xC7C7, 0xC898, 0xCAEB, 0xCC7D, 0xCE0E, 0xD0B3, 0xD2C0, 0xD456, 0xD625,
|
||||
0xD97A, 0xDB09, 0xDD9F, 0xDFEC, 0xE0E6, 0xE295, 0xE403, 0xE670, 0xE92F, 0xEB5C, 0xEDCA, 0xEFB9,
|
||||
0xF104, 0xF377, 0xF5E1, 0xF792, 0xF8CD, 0xFABE, 0xFC28, 0xFE5B)
|
||||
|
||||
DECODE_1576 = (
|
||||
0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x4020, 0x0008, 0x0009, 0x000A, 0x000B,
|
||||
0x000C, 0x000D, 0x2081, 0x2080, 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0C00, 0x0016, 0x0C02,
|
||||
0x0018, 0x0120, 0x001A, 0x0122, 0x4102, 0x0124, 0x4100, 0x4101, 0x0020, 0x0021, 0x0022, 0x4004,
|
||||
0x0024, 0x4002, 0x4001, 0x4000, 0x0028, 0x0110, 0x1800, 0x1801, 0x002C, 0x400A, 0x4009, 0x4008,
|
||||
0x0030, 0x0108, 0x0240, 0x0241, 0x0034, 0x4012, 0x4011, 0x4010, 0x0101, 0x0100, 0x0103, 0x0102,
|
||||
0x0105, 0x0104, 0x1401, 0x1400, 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x4060,
|
||||
0x0048, 0x0049, 0x0301, 0x0300, 0x004C, 0x1600, 0x0305, 0x0304, 0x0050, 0x0051, 0x0220, 0x0221,
|
||||
0x3000, 0x4200, 0x3002, 0x4202, 0x0058, 0x1082, 0x1081, 0x1080, 0x3008, 0x4208, 0x2820, 0x1084,
|
||||
0x0060, 0x0061, 0x0210, 0x0211, 0x0480, 0x0481, 0x4041, 0x4040, 0x0068, 0x2402, 0x2401, 0x2400,
|
||||
0x0488, 0x3100, 0x2810, 0x2404, 0x0202, 0x0880, 0x0200, 0x0201, 0x0206, 0x0884, 0x0204, 0x0205,
|
||||
0x0141, 0x0140, 0x0208, 0x0209, 0x2802, 0x0144, 0x2800, 0x2801, 0x0080, 0x0081, 0x0082, 0x0A00,
|
||||
0x0084, 0x0085, 0x2009, 0x2008, 0x0088, 0x0089, 0x2005, 0x2004, 0x2003, 0x2002, 0x2001, 0x2000,
|
||||
0x0090, 0x0091, 0x0092, 0x1048, 0x0602, 0x0C80, 0x0600, 0x0601, 0x0098, 0x1042, 0x1041, 0x1040,
|
||||
0x2013, 0x2012, 0x2011, 0x2010, 0x00A0, 0x00A1, 0x00A2, 0x4084, 0x0440, 0x0441, 0x4081, 0x4080,
|
||||
0x6000, 0x1200, 0x6002, 0x1202, 0x6004, 0x2022, 0x2021, 0x2020, 0x0841, 0x0840, 0x2104, 0x0842,
|
||||
0x2102, 0x0844, 0x2100, 0x2101, 0x0181, 0x0180, 0x0B00, 0x0182, 0x5040, 0x0184, 0x2108, 0x2030,
|
||||
0x00C0, 0x00C1, 0x4401, 0x4400, 0x0420, 0x0421, 0x0422, 0x4404, 0x0900, 0x0901, 0x1011, 0x1010,
|
||||
0x0904, 0x2042, 0x2041, 0x2040, 0x0821, 0x0820, 0x1009, 0x1008, 0x4802, 0x0824, 0x4800, 0x4801,
|
||||
0x1003, 0x1002, 0x1001, 0x1000, 0x0501, 0x0500, 0x1005, 0x1004, 0x0404, 0x0810, 0x1100, 0x1101,
|
||||
0x0400, 0x0401, 0x0402, 0x0403, 0x040C, 0x0818, 0x1108, 0x1030, 0x0408, 0x0409, 0x040A, 0x2060,
|
||||
0x0801, 0x0800, 0x0280, 0x0802, 0x0410, 0x0804, 0x0412, 0x0806, 0x0809, 0x0808, 0x1021, 0x1020,
|
||||
0x5000, 0x2200, 0x5002, 0x2202)
|
||||
|
||||
X14 = 0x00004000 # vector representation of X^14
|
||||
X8 = 0x00000100 # vector representation of X^8
|
||||
MASK7 = 0xffffff00 # auxiliary vector for testing
|
||||
GENPOL = 0x00000139 # generator polinomial, g(x)
|
||||
|
||||
def get_synd_1576(_pattern):
|
||||
aux = X14;
|
||||
if _pattern >= X8:
|
||||
while _pattern & MASK7:
|
||||
while not (aux & _pattern):
|
||||
aux = aux >> 1
|
||||
_pattern ^= (aux / X8) * GENPOL
|
||||
return _pattern
|
||||
|
||||
def encode(_data):
|
||||
value = (_data[0] >> 1) & 0x7F
|
||||
cksum = ENCODE_1676[value]
|
||||
_data[0] = cksum >> 8
|
||||
_data[1] = cksum & 0xFF
|
||||
return _data
|
||||
|
||||
def decode(_data):
|
||||
code = (_data[0] << 7) + (_data[1] >> 1)
|
||||
syndrome = get_synd_1576(code)
|
||||
error_pattern = DECODE_1576[syndrome]
|
||||
code ^= error_pattern
|
||||
return code >> 7
|
||||
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
# Used to execute the module directly to run built-in tests
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
if __name__ == '__main__':
|
||||
from bitarray import bitarray
|
||||
|
||||
EMB_bits = [0,0,0,0]
|
||||
EMB_bits[0] = bitarray('0001000') # 111100010
|
||||
EMB_bits[1] = bitarray('0001001') # 110010001
|
||||
EMB_bits[2] = bitarray('0001010') # 100000111
|
||||
EMB_bits[3] = bitarray('0001011') # 101110100
|
||||
print(EMB_bits)
|
||||
|
||||
|
||||
for seq in range(4):
|
||||
out = 0
|
||||
for bit in EMB_bits[seq]:
|
||||
out = (out << 1) | bit
|
||||
print(out)
|
||||
emb = ENCODE_1676[out]
|
||||
print(bin(emb))
|
|
@ -0,0 +1,151 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2016 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
# Copyright (C) 2015 by Jonathan Naylor G4KLX
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
###############################################################################
|
||||
|
||||
|
||||
|
||||
START_MASK = [0x96, 0x96, 0x96]
|
||||
END_MASK = [0x99, 0x99, 0x99]
|
||||
NUM_BYTES = 9
|
||||
NPAR = 3;
|
||||
POLY= [64, 56, 14, 1, 0, 0, 0, 0, 0, 0, 0, 0]
|
||||
|
||||
EXP_TABLE = (
|
||||
0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1D, 0x3A, 0x74, 0xE8, 0xCD, 0x87, 0x13, 0x26,
|
||||
0x4C, 0x98, 0x2D, 0x5A, 0xB4, 0x75, 0xEA, 0xC9, 0x8F, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0,
|
||||
0x9D, 0x27, 0x4E, 0x9C, 0x25, 0x4A, 0x94, 0x35, 0x6A, 0xD4, 0xB5, 0x77, 0xEE, 0xC1, 0x9F, 0x23,
|
||||
0x46, 0x8C, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x5D, 0xBA, 0x69, 0xD2, 0xB9, 0x6F, 0xDE, 0xA1,
|
||||
0x5F, 0xBE, 0x61, 0xC2, 0x99, 0x2F, 0x5E, 0xBC, 0x65, 0xCA, 0x89, 0x0F, 0x1E, 0x3C, 0x78, 0xF0,
|
||||
0xFD, 0xE7, 0xD3, 0xBB, 0x6B, 0xD6, 0xB1, 0x7F, 0xFE, 0xE1, 0xDF, 0xA3, 0x5B, 0xB6, 0x71, 0xE2,
|
||||
0xD9, 0xAF, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xBD, 0x67, 0xCE,
|
||||
0x81, 0x1F, 0x3E, 0x7C, 0xF8, 0xED, 0xC7, 0x93, 0x3B, 0x76, 0xEC, 0xC5, 0x97, 0x33, 0x66, 0xCC,
|
||||
0x85, 0x17, 0x2E, 0x5C, 0xB8, 0x6D, 0xDA, 0xA9, 0x4F, 0x9E, 0x21, 0x42, 0x84, 0x15, 0x2A, 0x54,
|
||||
0xA8, 0x4D, 0x9A, 0x29, 0x52, 0xA4, 0x55, 0xAA, 0x49, 0x92, 0x39, 0x72, 0xE4, 0xD5, 0xB7, 0x73,
|
||||
0xE6, 0xD1, 0xBF, 0x63, 0xC6, 0x91, 0x3F, 0x7E, 0xFC, 0xE5, 0xD7, 0xB3, 0x7B, 0xF6, 0xF1, 0xFF,
|
||||
0xE3, 0xDB, 0xAB, 0x4B, 0x96, 0x31, 0x62, 0xC4, 0x95, 0x37, 0x6E, 0xDC, 0xA5, 0x57, 0xAE, 0x41,
|
||||
0x82, 0x19, 0x32, 0x64, 0xC8, 0x8D, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xDD, 0xA7, 0x53, 0xA6,
|
||||
0x51, 0xA2, 0x59, 0xB2, 0x79, 0xF2, 0xF9, 0xEF, 0xC3, 0x9B, 0x2B, 0x56, 0xAC, 0x45, 0x8A, 0x09,
|
||||
0x12, 0x24, 0x48, 0x90, 0x3D, 0x7A, 0xF4, 0xF5, 0xF7, 0xF3, 0xFB, 0xEB, 0xCB, 0x8B, 0x0B, 0x16,
|
||||
0x2C, 0x58, 0xB0, 0x7D, 0xFA, 0xE9, 0xCF, 0x83, 0x1B, 0x36, 0x6C, 0xD8, 0xAD, 0x47, 0x8E, 0x01,
|
||||
0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1D, 0x3A, 0x74, 0xE8, 0xCD, 0x87, 0x13, 0x26, 0x4C,
|
||||
0x98, 0x2D, 0x5A, 0xB4, 0x75, 0xEA, 0xC9, 0x8F, 0x03, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC0, 0x9D,
|
||||
0x27, 0x4E, 0x9C, 0x25, 0x4A, 0x94, 0x35, 0x6A, 0xD4, 0xB5, 0x77, 0xEE, 0xC1, 0x9F, 0x23, 0x46,
|
||||
0x8C, 0x05, 0x0A, 0x14, 0x28, 0x50, 0xA0, 0x5D, 0xBA, 0x69, 0xD2, 0xB9, 0x6F, 0xDE, 0xA1, 0x5F,
|
||||
0xBE, 0x61, 0xC2, 0x99, 0x2F, 0x5E, 0xBC, 0x65, 0xCA, 0x89, 0x0F, 0x1E, 0x3C, 0x78, 0xF0, 0xFD,
|
||||
0xE7, 0xD3, 0xBB, 0x6B, 0xD6, 0xB1, 0x7F, 0xFE, 0xE1, 0xDF, 0xA3, 0x5B, 0xB6, 0x71, 0xE2, 0xD9,
|
||||
0xAF, 0x43, 0x86, 0x11, 0x22, 0x44, 0x88, 0x0D, 0x1A, 0x34, 0x68, 0xD0, 0xBD, 0x67, 0xCE, 0x81,
|
||||
0x1F, 0x3E, 0x7C, 0xF8, 0xED, 0xC7, 0x93, 0x3B, 0x76, 0xEC, 0xC5, 0x97, 0x33, 0x66, 0xCC, 0x85,
|
||||
0x17, 0x2E, 0x5C, 0xB8, 0x6D, 0xDA, 0xA9, 0x4F, 0x9E, 0x21, 0x42, 0x84, 0x15, 0x2A, 0x54, 0xA8,
|
||||
0x4D, 0x9A, 0x29, 0x52, 0xA4, 0x55, 0xAA, 0x49, 0x92, 0x39, 0x72, 0xE4, 0xD5, 0xB7, 0x73, 0xE6,
|
||||
0xD1, 0xBF, 0x63, 0xC6, 0x91, 0x3F, 0x7E, 0xFC, 0xE5, 0xD7, 0xB3, 0x7B, 0xF6, 0xF1, 0xFF, 0xE3,
|
||||
0xDB, 0xAB, 0x4B, 0x96, 0x31, 0x62, 0xC4, 0x95, 0x37, 0x6E, 0xDC, 0xA5, 0x57, 0xAE, 0x41, 0x82,
|
||||
0x19, 0x32, 0x64, 0xC8, 0x8D, 0x07, 0x0E, 0x1C, 0x38, 0x70, 0xE0, 0xDD, 0xA7, 0x53, 0xA6, 0x51,
|
||||
0xA2, 0x59, 0xB2, 0x79, 0xF2, 0xF9, 0xEF, 0xC3, 0x9B, 0x2B, 0x56, 0xAC, 0x45, 0x8A, 0x09, 0x12,
|
||||
0x24, 0x48, 0x90, 0x3D, 0x7A, 0xF4, 0xF5, 0xF7, 0xF3, 0xFB, 0xEB, 0xCB, 0x8B, 0x0B, 0x16, 0x2C,
|
||||
0x58, 0xB0, 0x7D, 0xFA, 0xE9, 0xCF, 0x83, 0x1B, 0x36, 0x6C, 0xD8, 0xAD, 0x47, 0x8E, 0x01, 0x00
|
||||
)
|
||||
|
||||
LOG_TABLE = (
|
||||
0x00, 0x00, 0x01, 0x19, 0x02, 0x32, 0x1A, 0xC6, 0x03, 0xDF, 0x33, 0xEE, 0x1B, 0x68, 0xC7, 0x4B,
|
||||
0x04, 0x64, 0xE0, 0x0E, 0x34, 0x8D, 0xEF, 0x81, 0x1C, 0xC1, 0x69, 0xF8, 0xC8, 0x08, 0x4C, 0x71,
|
||||
0x05, 0x8A, 0x65, 0x2F, 0xE1, 0x24, 0x0F, 0x21, 0x35, 0x93, 0x8E, 0xDA, 0xF0, 0x12, 0x82, 0x45,
|
||||
0x1D, 0xB5, 0xC2, 0x7D, 0x6A, 0x27, 0xF9, 0xB9, 0xC9, 0x9A, 0x09, 0x78, 0x4D, 0xE4, 0x72, 0xA6,
|
||||
0x06, 0xBF, 0x8B, 0x62, 0x66, 0xDD, 0x30, 0xFD, 0xE2, 0x98, 0x25, 0xB3, 0x10, 0x91, 0x22, 0x88,
|
||||
0x36, 0xD0, 0x94, 0xCE, 0x8F, 0x96, 0xDB, 0xBD, 0xF1, 0xD2, 0x13, 0x5C, 0x83, 0x38, 0x46, 0x40,
|
||||
0x1E, 0x42, 0xB6, 0xA3, 0xC3, 0x48, 0x7E, 0x6E, 0x6B, 0x3A, 0x28, 0x54, 0xFA, 0x85, 0xBA, 0x3D,
|
||||
0xCA, 0x5E, 0x9B, 0x9F, 0x0A, 0x15, 0x79, 0x2B, 0x4E, 0xD4, 0xE5, 0xAC, 0x73, 0xF3, 0xA7, 0x57,
|
||||
0x07, 0x70, 0xC0, 0xF7, 0x8C, 0x80, 0x63, 0x0D, 0x67, 0x4A, 0xDE, 0xED, 0x31, 0xC5, 0xFE, 0x18,
|
||||
0xE3, 0xA5, 0x99, 0x77, 0x26, 0xB8, 0xB4, 0x7C, 0x11, 0x44, 0x92, 0xD9, 0x23, 0x20, 0x89, 0x2E,
|
||||
0x37, 0x3F, 0xD1, 0x5B, 0x95, 0xBC, 0xCF, 0xCD, 0x90, 0x87, 0x97, 0xB2, 0xDC, 0xFC, 0xBE, 0x61,
|
||||
0xF2, 0x56, 0xD3, 0xAB, 0x14, 0x2A, 0x5D, 0x9E, 0x84, 0x3C, 0x39, 0x53, 0x47, 0x6D, 0x41, 0xA2,
|
||||
0x1F, 0x2D, 0x43, 0xD8, 0xB7, 0x7B, 0xA4, 0x76, 0xC4, 0x17, 0x49, 0xEC, 0x7F, 0x0C, 0x6F, 0xF6,
|
||||
0x6C, 0xA1, 0x3B, 0x52, 0x29, 0x9D, 0x55, 0xAA, 0xFB, 0x60, 0x86, 0xB1, 0xBB, 0xCC, 0x3E, 0x5A,
|
||||
0xCB, 0x59, 0x5F, 0xB0, 0x9C, 0xA9, 0xA0, 0x51, 0x0B, 0xF5, 0x16, 0xEB, 0x7A, 0x75, 0x2C, 0xD7,
|
||||
0x4F, 0xAE, 0xD5, 0xE9, 0xE6, 0xE7, 0xAD, 0xE8, 0x74, 0xD6, 0xF4, 0xEA, 0xA8, 0x50, 0x58, 0xAF
|
||||
)
|
||||
|
||||
# multiplication using logarithms
|
||||
def log_mult(a, b):
|
||||
if a == 0 or b == 0:
|
||||
return 0
|
||||
x = LOG_TABLE[a]
|
||||
y = LOG_TABLE[b]
|
||||
z = EXP_TABLE[x + y]
|
||||
return z
|
||||
|
||||
# Reed-Solomon (12,9) encoder
|
||||
def encode(_msg):
|
||||
assert len(_msg) == 9, 'RS129_encode error: Message not 9 bytes: %s' % print_hex(_msg)
|
||||
|
||||
parity = [0x00, 0x00, 0x00]
|
||||
|
||||
for i in range(NUM_BYTES):
|
||||
dbyte = _msg[i] ^ parity[NPAR - 1]
|
||||
for j in range(NPAR - 1, 0, -1):
|
||||
parity[j] = parity[j - 1] ^ log_mult(POLY[j], dbyte)
|
||||
parity[0] = log_mult(POLY[0], dbyte)
|
||||
return [parity[2], parity[1], parity[0]]
|
||||
|
||||
# Apply DMR XOR LC Header MASK
|
||||
def lc_header_mask(_parity):
|
||||
xor = [0,0,0]
|
||||
for i in range(len(_parity)):
|
||||
xor[i] = _parity[i] ^ START_MASK[i]
|
||||
return xor
|
||||
|
||||
# Apply DMR XOR LC Terminator MASK
|
||||
def lc_terminator_mask(_parity):
|
||||
xor = [0,0,0]
|
||||
for i in range(len(_parity)):
|
||||
xor[i] = _parity[i] ^ END_MASK[i]
|
||||
return xor
|
||||
|
||||
# All Inclusive function to take an LC string and provide the RS129 string to append
|
||||
def lc_header_encode(_message):
|
||||
bin_message = bytearray(_message)
|
||||
parity = encode(bin_message)
|
||||
masked_parity = lc_header_mask(parity)
|
||||
return bytes([masked_parity[0]]) + bytes([masked_parity[1]]) + bytes([masked_parity[2]])
|
||||
|
||||
# All Inclusive function to take an LC string and provide the RS129 string to append
|
||||
def lc_terminator_encode(_message):
|
||||
bin_message = bytearray(_message)
|
||||
parity = encode(bin_message)
|
||||
masked_parity = lc_terminator_mask(parity)
|
||||
return bytes([masked_parity[0]]) + bytes([masked_parity[1]]) + bytes([masked_parity[2]])
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from binascii import b2a_hex as ahex
|
||||
|
||||
# For testing the code
|
||||
def print_hex(_list):
|
||||
print('[{}]'.format(', '.join(hex(x) for x in _list)))
|
||||
|
||||
# Validation Example
|
||||
message = b'\x00\x10\x20\x00\x0c\x30\x2f\x9b\xe5'
|
||||
parity_should_be = b'\xda\x4d\x5a'
|
||||
print('Original Message: {}'.format(ahex(message)))
|
||||
print('Masked Parity Should be: {}'.format(ahex(parity_should_be)))
|
||||
|
||||
parity = lc_header_encode(message)
|
||||
print('Calculated Masked Parity is: {}'.format(ahex(parity)))
|
|
@ -0,0 +1,209 @@
|
|||
#!/usr/bin/env python
|
||||
#
|
||||
###############################################################################
|
||||
# Copyright (C) 2016-2018 Cortney T. Buffington, N0MJS <n0mjs@me.com>
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
###############################################################################
|
||||
|
||||
import ssl
|
||||
|
||||
from os.path import isfile, getmtime
|
||||
from time import time
|
||||
from urllib.request import urlopen
|
||||
from csv import reader as csv_reader
|
||||
from csv import DictReader as csv_dict_reader
|
||||
from binascii import b2a_hex as ahex
|
||||
|
||||
# Does anybody read this stuff? There's a PEP somewhere that says I should do this.
|
||||
__author__ = 'Cortney T. Buffington, N0MJS'
|
||||
__copyright__ = 'Copyright (c) 2016-2018 Cortney T. Buffington, N0MJS and the K0USY Group'
|
||||
__credits__ = 'Colin Durbridge, G4EML, Steve Zingman, N4IRS; Mike Zingman'
|
||||
__license__ = 'GNU GPLv3'
|
||||
__maintainer__ = 'Cort Buffington, N0MJS'
|
||||
__email__ = 'n0mjs@me.com'
|
||||
|
||||
|
||||
# CONSTANTS
|
||||
SUB_FIELDS = ('ID', 'CALLSIGN', 'NAME', 'CITY', 'STATE', 'COUNTRY', 'TYPE')
|
||||
PEER_FIELDS = ('ID', 'CALLSIGN', 'CITY', 'STATE', 'COUNTRY', 'FREQ', 'CC', 'OFFSET', 'TYPE', 'LINKED', 'TRUSTEE', 'INFO', 'OTHER', 'NETWORK', )
|
||||
TGID_FIELDS = ('ID', 'NAME')
|
||||
|
||||
|
||||
#************************************************
|
||||
# STRING UTILITY FUNCTIONS
|
||||
#************************************************
|
||||
|
||||
# Create a 2 byte hex string from an integer
|
||||
def hex_str_2(_int_id):
|
||||
return _int_id.to_bytes(2, 'big')
|
||||
|
||||
# Create a 3 byte hex string from an integer
|
||||
def hex_str_3(_int_id):
|
||||
return _int_id.to_bytes(3, 'big')
|
||||
|
||||
# Create a 4 byte hex string from an integer
|
||||
def hex_str_4(_int_id):
|
||||
return _int_id.to_bytes(4, 'big')
|
||||
|
||||
# Convert a hex string to an int (radio ID, etc.)
|
||||
def int_id(_hex_string):
|
||||
return int(ahex(_hex_string), 16)
|
||||
|
||||
|
||||
#************************************************
|
||||
# ID ALIAS FUNCTIONS
|
||||
#************************************************
|
||||
|
||||
# Download and build dictionaries for mapping number to aliases
|
||||
# Used by applications. These lookups take time, please do not shove them
|
||||
# into this file everywhere and send a pull request!!!
|
||||
# Download a new file if it doesn't exist, or is older than the stale time
|
||||
def try_download(_path, _file, _url, _stale,):
|
||||
no_verify = ssl._create_unverified_context()
|
||||
now = time()
|
||||
file_exists = isfile(_path+_file) == True
|
||||
if file_exists:
|
||||
file_old = (getmtime(_path+_file) + _stale) < now
|
||||
if not file_exists or (file_exists and file_old):
|
||||
try:
|
||||
with urlopen(_url, context=no_verify) as response, open(_path+_file, 'wb') as outfile:
|
||||
data = response.read()
|
||||
outfile.write(data)
|
||||
response.close()
|
||||
result = 'ID ALIAS MAPPER: \'{}\' successfully downloaded'.format(_file)
|
||||
except IOError:
|
||||
result = 'ID ALIAS MAPPER: \'{}\' could not be downloaded due to an IOError'.format(_file)
|
||||
else:
|
||||
result = 'ID ALIAS MAPPER: \'{}\' is current, not downloaded'.format(_file)
|
||||
return result
|
||||
|
||||
# LEGACY VERSION - MAKES A SIMPLE {INTEGER ID: 'CALLSIGN'} DICTIONARY
|
||||
def mk_id_dict(_path, _file):
|
||||
_dict = {}
|
||||
try:
|
||||
with open(_path+_file, 'r', encoding='latin1') as _handle:
|
||||
ids = csv_reader(_handle, dialect='excel', delimiter=',')
|
||||
for row in ids:
|
||||
try:
|
||||
_dict[int(row[0])] = (row[1])
|
||||
except:
|
||||
pass
|
||||
_handle.close
|
||||
return _dict
|
||||
except IOError:
|
||||
return _dict
|
||||
|
||||
# NEW VERSION - MAKES A FULL DICTIONARY OF INFORMATION BASED ON TYPE OF ALIAS FILE
|
||||
# BASED ON DOWNLOADS FROM DMR-MARC, TGID IS STILL A "SIMPLE" DICTIONARY
|
||||
def mk_full_id_dict(_path, _file, _type):
|
||||
_dict = {}
|
||||
if _type == 'subscriber':
|
||||
fields = SUB_FIELDS
|
||||
elif _type == 'peer':
|
||||
fields = PEER_FIELDS
|
||||
elif _type == 'tgid':
|
||||
fields = TGID_FIELDS
|
||||
try:
|
||||
with open(_path+_file, 'r', encoding='latin1') as _handle:
|
||||
ids = csv_dict_reader(_handle, fieldnames=fields, restkey='OTHER', dialect='excel', delimiter=',')
|
||||
for row in ids:
|
||||
for item in row:
|
||||
try:
|
||||
_dict[int(row['ID'])] = dict(row)
|
||||
except:
|
||||
pass
|
||||
_handle.close
|
||||
return (_dict)
|
||||
except IOError:
|
||||
return _dict
|
||||
|
||||
# THESE ARE THE SAME THING FOR LEGACY PURPOSES
|
||||
def get_alias(_id, _dict, *args):
|
||||
if type(_id) == str:
|
||||
_id = int_id(_id)
|
||||
if _id in _dict:
|
||||
if args:
|
||||
retValue = []
|
||||
for _item in args:
|
||||
try:
|
||||
retValue.append(_dict[_id][_item])
|
||||
except TypeError:
|
||||
return _dict[_id]
|
||||
return retValue
|
||||
else:
|
||||
return _dict[_id]
|
||||
return _id
|
||||
|
||||
def get_info(_id, _dict, *args):
|
||||
if type(_id) == str:
|
||||
_id = int_id(_id)
|
||||
if _id in _dict:
|
||||
if args:
|
||||
retValue = []
|
||||
for _item in args:
|
||||
try:
|
||||
retValue.append(_dict[_id][_item])
|
||||
except TypeError:
|
||||
return _dict[_id]
|
||||
return retValue
|
||||
else:
|
||||
return _dict[_id]
|
||||
return _id
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
||||
# Try updating peer aliases file
|
||||
result = try_download('/tmp/', 'peers.csv', 'https://www.radioid.net/static/rptrs.csv', 0)
|
||||
print(result)
|
||||
# Try updating subscriber aliases file
|
||||
result = try_download('/tmp/', 'subscribers.csv', 'https://www.radioid.net/static/users.csv', 0)
|
||||
print(result)
|
||||
|
||||
# Make Dictionaries
|
||||
peer_ids = mk_id_dict('/tmp/', 'peers.csv')
|
||||
if peer_ids:
|
||||
print('ID ALIAS MAPPER: peer_ids dictionary is available')
|
||||
|
||||
subscriber_ids = mk_id_dict('/tmp/', 'subscribers.csv')
|
||||
if subscriber_ids:
|
||||
print('ID ALIAS MAPPER: subscriber_ids dictionary is available')
|
||||
|
||||
full_peer_ids = mk_full_id_dict('/tmp/', 'peers.csv', 'peer')
|
||||
if peer_ids:
|
||||
print('ID ALIAS MAPPER: full_peer_ids dictionary is available')
|
||||
|
||||
full_subscriber_ids = mk_full_id_dict('/tmp/', 'subscribers.csv', 'subscriber')
|
||||
if subscriber_ids:
|
||||
print('ID ALIAS MAPPER: full_subscriber_ids dictionary is available')
|
||||
|
||||
print(get_alias(3120101, subscriber_ids))
|
||||
print(get_info(3120101, subscriber_ids))
|
||||
print(get_alias(3120101, full_subscriber_ids))
|
||||
print(get_info(3120101, full_subscriber_ids))
|
||||
print(get_alias(31201010, subscriber_ids))
|
||||
print(get_info(31201010, subscriber_ids))
|
||||
|
||||
print(get_alias(312000, peer_ids))
|
||||
print(get_info(312000, peer_ids))
|
||||
print(get_alias(312000, full_peer_ids))
|
||||
print(get_info(312000, full_peer_ids))
|
||||
|
||||
print(hex_str_2(65535))
|
||||
print(hex_str_3(65535))
|
||||
print(ahex(hex_str_4(13120101)))
|
||||
print(int_id(b'\x00\xc8\x32\x65'))
|
||||
|
Loading…
Reference in New Issue