mirror of
https://github.com/n0mjs710/dmr_utils3
synced 2025-12-21 07:45:39 +08:00
Initial commit
This commit is contained in:
277
ambe_utils.py
Executable file
277
ambe_utils.py
Executable file
@@ -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()
|
||||
Reference in New Issue
Block a user