Project

General

Profile

Bug #1629 » viterbi.py

tnt, 03/03/2016 08:37 PM

 
1

    
2

    
3

    
4
class ConvolutionalCode(object):
5

    
6
	def __init__(self, block_len, k, polys, name=None, description=None):
7
		# Save simple params
8
		self.block_len = block_len
9
		self.k = k
10
		self.rate_inv = len(polys)
11

    
12
		# Infos
13
		self.name = name
14
		self.description = description
15

    
16
		# Handle polynoms (and check for recursion)
17
		self.polys = [(1,1) if x[0]==x[1] else x for x in polys]
18

    
19
		rp = [x[1] for x in self.polys if x[1] != 1]
20
		if rp:
21
			if not all([x == rp[0] for x in rp]):
22
				raise ValueError("Bad polynoms: Can't have multiple different divider polynoms !")
23
			if not all([x[0]==1 for x in polys if x[1]==1]):
24
				raise ValueError("Bad polynoms: Can't have a '1' divider with a non '1' dividend in a recursive code")
25
			self.poly_divider = rp[0]
26
		else:
27
			self.poly_divider = 1
28

    
29
	@property
30
	def recursive(self):
31
		return self.poly_divider != 1
32

    
33
	def _combine(self, src, sel, nb):
34
		x = src & sel
35
		fn_xor = lambda x,y: x^y
36
		return reduce(fn_xor, [(x >> n) & 1 for n in range(nb)])
37

    
38
	@property
39
	def _state_mask(self):
40
		return ((1<<(self.k-1)) - 1)
41

    
42
	def next_state(self, state, bit):
43
		nb = self._combine(
44
			(state << 1) | bit,
45
			self.poly_divider,
46
			self.k,
47
		)
48
		return ((state << 1) | nb) & self._state_mask
49

    
50
	def next_term_state(self, state):
51
		return (state << 1) & self._state_mask
52

    
53
	def next_output(self, state, bit, ns=None):
54
		# Next state bit
55
		if ns is None:
56
			ns = self.next_state(state, bit)
57

    
58
		src  = (ns & 1) | (state << 1)
59

    
60
		# Scan polynoms
61
		rv = []
62
		for p_n, p_d in self.polys:
63
			if self.recursive and p_d == 1:
64
				o = bit	# No choice ... (systematic output in recursive case)
65
			else:
66
				o = self._combine(src, p_n, self.k)
67
			rv.append(o)
68

    
69
		return rv
70

    
71
	def next_term_output(self, state, ns=None):
72
		# Next state bit
73
		if ns is None:	
74
			ns = self.next_term_state(state)
75

    
76
		src = (ns & 1) | (state << 1)
77

    
78
		# Scan polynoms
79
		rv = []
80
		for p_n, p_d in self.polys:
81
			if self.recursive and p_d == 1:
82
				# Systematic output are replaced when in 'termination' mode
83
				o = self._combine(src, self.poly_divider, self.k)
84
			else:
85
				o = self._combine(src, p_n, self.k)
86
			rv.append(o)
87

    
88
		return rv
89

    
90
	def next(self, state, bit):
91
		ns = self.next_state(state, bit)
92
		nb = self.next_output(state, bit, ns=ns)
93
		return ns, nb
94

    
95
	def next_term(self, state):
96
		ns = self.next_term_state(state)
97
		nb = self.next_term_output(state, ns=ns)
98
		return ns, nb
99

    
100
	def gen_tables(self):
101

    
102
		pack = lambda n: sum([x << (self.rate_inv-i-1) for i,x in enumerate(n)])
103
		num_states = 1 << (self.k-1)
104

    
105
		# next_output
106
		print "--- [next output]"
107
		for state in range(num_states):
108
			print "{ %2d, %2d }, " % (
109
				pack(self.next_output(state, 0)),
110
				pack(self.next_output(state, 1))
111
			)
112

    
113
		# next_state
114
		print "--- [next state]"
115
		for state in range(num_states):
116
			print "{ %2d, %2d }, " % (
117
				self.next_state(state, 0),
118
				self.next_state(state, 1)
119
			)
120

    
121
		if self.recursive:
122
			# next_term_output
123
			print "--- [next term output]"
124
			d = []
125
			for state in range(num_states):
126
				d.append("%2d,%s" % (
127
					pack(self.next_term_output(state)),
128
					'\n' if state % 16 == 15 else ' ',
129
				))
130
			print "{"
131
			print ''.join(d)
132
			print "};"
133

    
134
			# next_term_state
135
			print "--- [next term state]"
136
			d = []
137
			for state in range(num_states):
138
				d.append("%2d,%s" % (
139
					self.next_term_state(state),
140
					'\n' if state % 16 == 15 else ' ',
141
				))
142
			print "{"
143
			print ''.join(d)
144
			print "};"
145

    
146
poly = lambda *args: sum([(1<<x) for x in args])
147

    
148
# 228 bits blocks, rate 1/2, k=5
149
#  G0 = 1 + D3 + D4
150
#  G1 = 1 + D + D3 + D4
151
xcch_code = ConvolutionalCode(
152
	224, 5,
153
	[
154
		( poly(0,3,4),		1 ),
155
		( poly(0,1,3,4),	1 ),
156
	],
157
)
158

    
159
# 124 bits
160
#  G4/G6 = 1 + D2 + D3 + D5 + D6 / 1 + D + D2 + D3 + D4 + D6
161
#  G5/G6 = 1 + D + D4 + D6 / 1 + D + D2 + D3 + D4 + D6
162
#  G6/G6 = 1
163
#  G6/G6 = 1
164
tch_afs_5_9_code = ConvolutionalCode(
165
	124, 7,
166
	[
167
		( poly(0,2,3,5,6),	poly(0,1,2,3,4,6) ),
168
		( poly(0,1,4,6),	poly(0,1,2,3,4,6) ),
169
		( 1,				1),
170
		( 1,				1),
171
	],
172
)
173

    
174
#  G1 = 1 + D           + D4
175
#  G2 = 1     + D2 + D3 + D4
176
#  G3 = 1 + D + D2      + D4
177
#  G4 = 1 + D      + D3 + D4
178
tetra_rcpc_code = ConvolutionalCode(
179
	288, 5,
180
	[
181
		( poly(0,1,4),		1 ),
182
		( poly(0,2,3,4),	1 ),
183
		( poly(0,1,2,4),	1 ),
184
		( poly(0,1,3,4),	1 ),
185
	],
186
)
187

    
188

    
189
tetra_rcpc_tch_code = ConvolutionalCode(
190
	288, 5,
191
	[
192
		( poly(0,1,2,3,4),		1 ),
193
		( poly(0,1,3,4),		1 ),
194
		( poly(0,2,4),			1 ),
195
	],
196
)
(1-1/2)
Add picture from clipboard (Maximum size: 48.8 MB)