comparison gsm-fw/ccd/freq_list_com.c @ 648:970d6199f2c5

gsm-fw/ccd/*.[ch]: initial import from the LoCosto source
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Thu, 04 Sep 2014 05:48:57 +0000
parents
children
comparison
equal deleted inserted replaced
647:a60b375014e3 648:970d6199f2c5
1 /*
2 +-----------------------------------------------------------------------------
3 | Project : CCD
4 | Modul : freq_list_com.c
5 +-----------------------------------------------------------------------------
6 | Copyright 2004 Texas Instruments Deutschland GmbH
7 | All rights reserved.
8 |
9 | This file is confidential and a trade secret of Texas
10 | Instruments Deutschland GmbH
11 | The receipt of or possession of this file does not convey
12 | any rights to reproduce or disclose its contents or to
13 | manufacture, use, or sell anything it may describe, in
14 | whole, or in part, without the specific written consent of
15 | Texas Instruments Deutschland GmbH.
16 +-----------------------------------------------------------------------------
17 | Purpose : Definitions of common functions for decoding of types FDD_CI,
18 | TDD_CI and FREQ_LIST.
19 +-----------------------------------------------------------------------------
20 */
21
22 #define CDC_FREQ_LIST_COM_C
23
24 /*
25 * standard definitions like GLOBAL, UCHAR, ERROR etc.
26 */
27 #include "typedefs.h"
28 #include "header.h"
29
30 /*
31 * Types and functions for bit access and manipulation
32 */
33 #include "ccd_globs.h"
34 #include "bitfun.h"
35
36 /*
37 * Error codes and prototypes of exported functions by CCD
38 */
39 #include "ccdapi.h"
40
41 /*
42 * Prototypes of ccd internal functions
43 */
44 #include "ccd.h"
45
46 #ifndef RUN_INT_RAM
47 U8 ByteBitMask[]= {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x1};
48 #endif /* !RUN_INT_RAM */
49
50 #ifndef RUN_INT_RAM
51 /*
52 * The following table indicates the number of W-parameters and their
53 * length in bits. A length of zero indicates the end of the table.
54 * For frequency lists the W-parameter in the 1024 range starts from
55 * bit 6 of the information element.
56 */
57 const T_W_PARAM param_1024[9] =
58 {
59 /*
60 * length count
61 */
62 10, 1,
63 9, 2,
64 8, 4,
65 7, 8,
66 6, 16,
67 5, 32,
68 4, 64,
69 3, 128,
70 0, 0
71 };
72 #endif /* !RUN_INT_RAM */
73
74 #ifndef RUN_INT_RAM
75 /*
76 * The following table indicates the number of W-parameters and their
77 * length in bits. A length of zero indicates the end of the table.
78 * For frequency lists the W-parameter in the 512 range starts from
79 * bit 7 of the information element.
80 */
81 const T_W_PARAM param_512[10] =
82 {
83 /*
84 * length count
85 */
86 10, 1,
87 9, 1,
88 8, 2,
89 7, 4,
90 6, 8,
91 5, 16,
92 4, 32,
93 3, 64,
94 2, 128,
95 0, 0
96 };
97 #endif /* !RUN_INT_RAM */
98
99 #ifndef RUN_INT_RAM
100 /* Attention for RUN_...: static function */
101 /*
102 +--------------------------------------------------------------------+
103 | PROJECT : CCD FUNCTION : for_modulo |
104 +--------------------------------------------------------------------+
105
106 PURPOSE : A modulo calculation function. The standard C-Operator
107 fails for negative values! (e.g. -4 mod 6 is 2 and not 4).
108
109 */
110
111 /* static */ long for_modulo (long a, long b)
112 {
113 long result;
114
115 /* Use standard C-Operator for calculation. */
116 result = a % b;
117
118 /* Correct the result for negative values. */
119 if (result < 0)
120 {
121 result += b;
122 }
123
124 return result;
125 }
126 #endif /* !RUN_INT_RAM */
127
128 #ifndef RUN_INT_RAM
129 /* Attention for RUN_...: static function */
130 /*
131 +--------------------------------------------------------------------+
132 | PROJECT : CCD FUNCTION : for_smodulo |
133 +--------------------------------------------------------------------+
134
135 PURPOSE : Similar to the modulo operator, but 0 smod n is n and
136 not 0. Same problem for negative values with the standard
137 C-Operator.
138
139 */
140 static long for_smodulo (long a, long b)
141 {
142 long result;
143
144 /* Use standard C-Operator for calculation. */
145 result = a % b;
146
147 /* Correct the result for negative values. */
148 if (result < 0)
149 {
150 result += b;
151 }
152
153 /* Special handling for result equal 0 */
154 if (result EQ 0)
155 {
156 result = b;
157 }
158
159 return result;
160 }
161 #endif /* !RUN_INT_RAM */
162
163 #ifndef RUN_INT_RAM
164 /* Attention for RUN_...: static function */
165 /*
166 +--------------------------------------------------------------------+
167 | PROJECT : CCD FUNCTION : for_get_generation |
168 +--------------------------------------------------------------------+
169
170 PURPOSE : The function calculates the greatest power of 2 of the given
171 value. The algorithm simply looks to the position of the
172 highest bit.
173
174 */
175
176 static U16 for_get_generation (U16 value)
177 {
178 int result = 0;
179 int i;
180
181
182 /* Check all 16 bit positions. */
183 for (i = 0; i < 16; i++)
184 {
185 /* If bit is set, store the position. */
186 if (value & 1)
187 {
188 result = i + 1;
189 }
190
191 /* Shift value to have the next bit for comparision. */
192 value = value >> 1;
193 }
194
195 /* Return the highest position. */
196 return result;
197 }
198 #endif /* !RUN_INT_RAM */
199
200 #ifndef RUN_INT_RAM
201 /*
202 +--------------------------------------------------------------------+
203 | PROJECT : CCD FUNCTION : cdc_decode_frequencies |
204 +--------------------------------------------------------------------+
205
206 PURPOSE : The algorithm is according GSM 4.08 Annex J. It calculates
207 a frequency hopping list from the W-parameter.
208
209 */
210 void cdc_decode_frequencies (short original_range,
211 short *w,
212 short offset,
213 U8 callerID,
214 T_CCD_Globs *globs)
215 {
216 short g;
217 short k;
218 short j;
219 short index;
220 short n;
221 short range;
222 U16 channel;
223 U16 bitposition;
224 U8 *BitmapInStruct = globs->pstruct + globs->pstructOffs;
225 U16 first = 0;
226 U16 last = BITOFFSET_LIST;
227 U16 num = 0;
228 BOOL ReadW = TRUE;
229
230 #ifdef DEBUG_CCD
231 TRACE_CCD (globs, "cdc_decode_frequencies()");
232 #endif
233
234 if (callerID != TDD_CI_LIST && w[0] == 0)
235 ReadW = FALSE;
236 for (k = 1; ReadW; k++)
237 {
238 ReadW = (w[k-1] != 0) ? 1 : 0;
239 /*
240 * The next loop follows the tree from child to parent,
241 * from the node of index K to the root (index 1). For each iteration the
242 * node of index INDEX is tackled. The corresponding range is RANGE, and N
243 * is the value of the element in the range defined by the node.
244 *
245 * The data are set to their initial values
246 */
247 index = k;
248 n = w[index-1];
249 g = for_get_generation (index);
250 j = (1 << (g-1));
251 range = original_range / j;
252
253 while (index > 1)
254 {
255 /*
256 * Due to the assumption that the original range is a power of two minus one,
257 * the range for the parent node can be easily computed, and does not depend
258 * upon whether the current node is a left or right child
259 */
260 g = for_get_generation (index);
261 j = (1 << (g-1));
262 range = 2 * range + 1;
263
264 /*
265 * Let us note J := 2 g-1 , g being the generation of node INDEX. We have J =
266 * GREATEST_POWER_OF_2_LESSER_OR_EQUAL_TO(INDEX). The numbering used in the tree
267 * is such that the nodes of index J to J + J/2 - 1 are left children, and the nodes
268 * of index J/2 to J+J-1 are right children. Hence an easy test to
269 * distinguish left and right children:
270 */
271 if (2 * index < 3 * j)
272 {
273 /*
274 * The next computation gives the index of the parent node of the node of index
275 * INDEX, for a left child :
276 */
277 index = index - j / 2;
278
279 /*
280 * The next formula is the inverse of the renumbering appearing in the encoding
281 * for a left child. It gives the value of the parent node in the range defined
282 * by the grand-parent node:
283 */
284 n = (short)for_smodulo (n + w[index-1] + (range-1) / 2, range);
285 }
286 else
287 {
288 /*
289 * The next computation gives the index of the parent node of the node of index
290 * INDEX, for a right child :
291 */
292 index = index - j;
293
294 /*
295 * The next formula is the inverse of the renumbering appearing in the encoding
296 * for a right child:
297 */
298 n = (short)for_smodulo (n + w[index-1], range);
299 }
300 }
301
302 /*
303 * Write the calculated number for non-frequency types.
304 * For TDD_CI and TDD_CI: offset = 0 and original_range = 1023.
305 */
306 channel = (U16)for_modulo (n+offset, 1024);
307 if (callerID == FDD_CI_LIST || callerID == TDD_CI_LIST)
308 {
309 *(U16*)(globs->pstruct + globs->pstructOffs) = (U16)channel;
310 globs->pstructOffs += 2;
311 }
312 /* Set the calculated channel number for frequency channel list.*/
313 else
314 {
315 if (channel == 0)
316 {
317 bitposition = 0;
318 }
319 else
320 {
321 bitposition = (U16)(BITOFFSET_LIST - channel);
322 }
323 if (first > bitposition)
324 first = bitposition;
325 if (last < bitposition)
326 last = bitposition;
327 num++;
328 BitmapInStruct[bitposition >> 3] |= ByteBitMask[bitposition & 7];
329 }
330 }
331
332 /* For the bitmap type print the helpful information into the structure. */
333 if (callerID == FREQUENCY_LIST)
334 {
335 *(U16*) (BitmapInStruct - 6) = first;
336 *(U16*) (BitmapInStruct - 6) = last;
337 *(U16*) (BitmapInStruct - 2) = num;
338 }
339 }
340 #endif /* !RUN_INT_RAM */
341
342 #ifndef RUN_INT_RAM
343 /*
344 +--------------------------------------------------------------------+
345 | PROJECT : CCD FUNCTION : cdc_decode_param |
346 +--------------------------------------------------------------------+
347
348 PURPOSE : The information element contains a list of W-parameter.
349 The table param indicates how many W-parameter from each
350 length shall be inside. The function converts the bitstream
351 of the W-parameter to an array of W-parameter 16 bit values.
352
353 */
354
355 void cdc_decode_param (const T_W_PARAM *param,
356 short *w,
357 U16 ListLength,
358 T_CCD_Globs *globs)
359 {
360 U8 end_detected = FALSE;
361 U16 w_index = 0;
362 U16 length = ListLength;
363 U16 act_length = param->length;
364 U16 act_counter = param->count;
365 U32 lvalue;
366
367 #ifdef DEBUG_CCD
368 TRACE_CCD (globs, "cdc_decode_param()");
369 #endif
370
371 /*
372 * Decode values in the list until the end of the IE is detected.
373 */
374 while (!end_detected)
375 {
376 /*
377 * If the length of the next W-parameter is greater than eight bits,
378 * use ccd_decodeLong function. For smaller length use the
379 * ccd_decodeByte function to extract the W-parameter from the bitstream.
380 */
381 lvalue = bf_getBits (act_length, globs);
382 w[w_index++] = (short)lvalue;
383
384 /*
385 * w = 0 is equal to end of list if it is not the w(0) !!!
386 * (The case w(0)=0 possible for frequency list, but maybe not for other
387 * cases this algorithm is invoked.
388 */
389 if (w_index != 1 && w[w_index-1] == 0)
390 {
391 end_detected = TRUE;
392 }
393
394 /* End of buffer is equal to end of list. */
395 if (length > act_length)
396 {
397 length -= act_length;
398 }
399 else
400 {
401 end_detected = TRUE;
402 }
403
404 /* Check if all w parameters of one size are read. */
405 if (--act_counter == 0)
406 {
407 param++;
408 act_length = param->length;
409 act_counter = param->count;
410 }
411 /* End of parameter table */
412 if ((act_length == 0) || (length < act_length))
413 {
414 end_detected = TRUE;
415 }
416 }
417
418 /* Add an end identifier. */
419 w[w_index++] = 0;
420 }
421 #endif /* !RUN_INT_RAM */