comparison comlib/cl_list.c @ 0:75a11d740a02

initial import of gsm-fw from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 09 Jun 2016 00:02:41 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:75a11d740a02
1 /*
2 +-----------------------------------------------------------------------------
3 | Project :
4 | Modul :
5 +-----------------------------------------------------------------------------
6 | Copyright 2002 Texas Instruments Berlin, AG
7 | All rights reserved.
8 |
9 | This file is confidential and a trade secret of Texas
10 | Instruments Berlin, AG
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 Berlin, AG.
16 +-----------------------------------------------------------------------------
17 | Purpose : This module defines the functions for the List
18 | processing functions used in components RR/PL of the mobile station.
19 +-----------------------------------------------------------------------------
20 */
21
22 #ifndef CL_LIST_C
23 #define CL_LIST_C
24
25 #include "config.h"
26 #include "fixedconf.h"
27
28 #define ENTITY_RR
29 #define ENTITY_PL
30
31 /*==== INCLUDES ===================================================*/
32
33 #include <string.h>
34 #include <stdlib.h>
35 #include <stddef.h>
36 #include "typedefs.h"
37 #include "message.h"
38 #include "vsi.h"
39 #include "gsm.h"
40 #include "prim.h"
41 #include "cl_list.h"
42
43 /*==== CONST ======================================================*/
44 #ifdef TI_PS_FF_QUAD_BAND_SUPPORT
45 #define INRANGE(min, x, max) ((unsigned)(x-min) <= (max-min))
46 #endif
47
48 /*==== VARIABLES ==================================================*/
49 LOCAL const BYTE ByteBitMask[]= {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x1};
50
51 /*==== EXPORT =====================================================*/
52
53 /*==== PRIVATE FUNCTIONS ==========================================*/
54 LOCAL UBYTE srv_is_not_in_list (USHORT * channels,
55 USHORT new_channel,
56 USHORT size);
57
58
59 /*==== PUBLIC FUNCTIONS ===========================================*/
60 /*
61 * List processing Functions
62 *
63 * RR uses a lot of channel lists. They are organized internally as bitmaps.
64 * In the following a set of functions is defined for access to this lists:
65 *
66 * srv_set_channel
67 * srv_unset_channel
68 * srv_get_channel
69 * srv_create_list
70 * srv_clear_list
71 * srv_copy_list
72 * srv_compare_list
73 * srv_merge_list
74 * srv_is_empty_list
75 * srv_create_chan_mob_alloc
76 *
77 * The size of the internal channel lists depends on the supported frequency
78 * band:
79 *
80 * STD=1 (STD_900) GSM 900
81 * STD=2 (STD_EGSM) E-GSM
82 * STD=3 (STD_1900) PCS 1900
83 * STD=4 (STD_1800) DCS 1800
84 * STD=5 (STD_DUAL) GSM 900 / DCS 1800 DUALBAND
85 * STD=6 (STD_DUAL_EGSM) GSM 900 / E-GSM / DCS 1800 DUALBAND
86 * STD=7 (STD_850) GSM 850
87 * STD=8 (STD_DUAL_US) GSM 850 / PCS 1900 DUALBAND
88 *
89 * We use a compressed bit array to store the list of channels.
90 * Dependent on the configured or found frequency bands the bit array
91 * needs several numbers of bytes. For the representation of the individual
92 * bits in the array we need the function scr_channel_bit(), setBit(),
93 * resetBit() and getBit().
94 *
95 */
96
97 /*
98 +--------------------------------------------------------------------+
99 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
100 | STATE : code ROUTINE : setBit |
101 +--------------------------------------------------------------------+
102
103 PURPOSE : sets bit.
104
105 */
106
107 LOCAL void setBit (UBYTE* bitstream, unsigned bitindex)
108 {
109 bitstream[bitindex >> 3] |= ByteBitMask[bitindex & 7];
110 }
111
112
113 /*
114 +--------------------------------------------------------------------+
115 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
116 | STATE : code ROUTINE : resetBit |
117 +--------------------------------------------------------------------+
118
119 PURPOSE : Resets bit.
120
121 */
122
123 LOCAL void resetBit (UBYTE* bitstream, unsigned bitindex)
124 {
125 bitstream[bitindex >> 3] &= ~ByteBitMask[bitindex & 7];
126 }
127
128 /*
129 +--------------------------------------------------------------------+
130 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
131 | STATE : code ROUTINE : getBit |
132 +--------------------------------------------------------------------+
133
134 PURPOSE : Gets bit.
135
136 */
137
138
139 LOCAL BYTE getBit (UBYTE* bitstream, unsigned bitindex)
140 {
141 unsigned ByteIdx = bitindex >> 3;
142
143 if (bitstream[ByteIdx])
144 return (bitstream[ByteIdx] & ByteBitMask[bitindex & 7]) ? 1 : 0;
145 else
146 return 0;
147 }
148
149 /*
150 +--------------------------------------------------------------------+
151 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
152 | STATE : code ROUTINE : scr_channel_bit |
153 +--------------------------------------------------------------------+
154
155 PURPOSE : calculate bit position in the bitstream for a given
156 channel and execute function dependent on mode.
157
158 */
159
160 GLOBAL UBYTE scr_channel_bit(T_LIST * list, int channel, int mode)
161 {
162 int bitposition = -1;
163 UBYTE ret = 0;
164
165 /*
166 * a more efficient way of range checking for ARM
167 * (according to application note 34, ARM DAI 0034A, January 1998)
168 *
169 * For the following code:
170 * if (channel >= low_channel AND channel <= high_channel)
171 * bitposition = ...;
172 *
173 * exist the faster way to implemented this:
174 * if ((unsigned)(channel - low_channel) <= (high_channel - low_channel)
175 * bitposition = ...;
176 *
177 * Future versions of the compiler will perform this optimization
178 * automatically.
179 *
180 * We use the follwing macro:
181 * #define INRANGE(min, x, max) ((unsigned)(x-min) <= (max-min))
182 */
183 if(channel EQ CHANNEL_0)
184 channel = CHANNEL_0_INTERNAL;
185
186 bitposition = BITOFFSET_LIST - channel;
187 /*if (channel EQ CHANNEL_0)
188 bitposition = (USHORT)(BITOFFSET_DUAL_EGSM_B - CHANNEL_0_INTERNAL);
189 else if (INRANGE(LOW_CHANNEL_900,channel,HIGH_CHANNEL_900))
190 bitposition = (USHORT)(BITOFFSET_DUAL_EGSM_A - channel);
191 else if (INRANGE(LOW_CHANNEL_EGSM,channel,HIGH_CHANNEL_EGSM))
192 bitposition = (USHORT)(BITOFFSET_DUAL_EGSM_B - channel);
193 else if (INRANGE(LOW_CHANNEL_1800,channel,HIGH_CHANNEL_1800))
194 bitposition = (USHORT)(BITOFFSET_DUAL_EGSM_C - channel);
195 if (INRANGE(LOW_CHANNEL_850,channel,HIGH_CHANNEL_850))
196 bitposition = (USHORT)(BITOFFSET_DUAL_US_A - channel);
197 else if (INRANGE(LOW_CHANNEL_1900,channel,HIGH_CHANNEL_1900))
198 bitposition = (USHORT)(BITOFFSET_DUAL_US_B - channel);
199 */
200 if (bitposition >=0)
201 {
202 switch (mode)
203 {
204 case SET_CHANNEL_BIT:
205 setBit (list->channels, bitposition);
206 break;
207 case RESET_CHANNEL_BIT:
208 resetBit (list->channels, bitposition);
209 break;
210 case GET_CHANNEL_BIT:
211 ret = getBit (list->channels, bitposition);
212 break;
213 case CHECK_CHANNEL:
214 ret = 1;
215 break;
216 }
217 }
218 return ret;
219 }
220
221 /*
222 +--------------------------------------------------------------------+
223 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
224 | STATE : code ROUTINE : srv_create_list |
225 +--------------------------------------------------------------------+
226
227 PURPOSE : Creates a frequency list in USHORT format from the
228 bit list. USHORT format means an array of USHORTs
229 followed by NOT_PRESENT_16BIT (0xFFFF), except for the
230 case when all elements of the array are used, i.e. the
231 array's space is fully occupied.
232 In this function the channels are just converted between
233 the formats, any semantic errors are not checked here, ie.
234 if the MS is 1800-only and the list contains a 900 channel
235 this will be converted even if this leads to an error.
236 This has to be handled by the caller.
237
238 Parameters:
239 list - [in] is the input list.
240 channel_array - [out] converted list.
241 size - [in] defines the maximum number of channels
242 in the list.
243 zero_at_start - [in] specifies where the CHANNEL_0 should be
244 put:
245 TRUE - at the start of the list
246 FALSE - at the end of the list
247 start_index - [in] specifies a index into the channel_array.
248 new channels are added at the positions
249 following and including the index:
250 channel_array[start_index] to
251 channel_array[size-1]
252
253 If the start_index is not equal zero it is
254 also checked if the new channel is already
255 in the channel_array list (from
256 channel_array[0] to
257 channel_array[start_index-1])
258
259 If the start_index is equal zero the
260 above check is not performed.
261
262 Return Value:
263 number of elements added + start_index
264
265 */
266
267 GLOBAL int srv_create_list (T_LIST * list, USHORT * channel_array, USHORT size,
268 UBYTE zero_at_start, USHORT start_index)
269 {
270 int BitOffset, Idx;
271 unsigned int ByteValue, BitMask, LeftMask;
272 int i = start_index;
273 UBYTE *pch;
274 USHORT *parray = &channel_array[start_index];
275
276 pch = &list->channels[T_LIST_MAX_SIZE-1];
277 for(Idx = T_LIST_MAX_SIZE-1; Idx >= 0 AND i < size; Idx--, pch--)
278 {
279 /*
280 * check and add all channels
281 */
282 if ((ByteValue = *pch) NEQ 0)
283 {
284 /* byte contains set bits */
285
286 /* check single bits */
287 for (BitOffset=7, BitMask=0x01, LeftMask=0xfe;
288 BitOffset>=0;
289 BitOffset--, BitMask<<=1, LeftMask<<=1)
290 {
291 if (ByteValue & BitMask)
292 {
293 *parray = BITOFFSET_LIST - (BitOffset+(Idx<<3));
294 if(!start_index OR
295 srv_is_not_in_list (channel_array, *parray, start_index))
296 {
297 /* if the check is ok, ie:
298 * always add channel, or the channel has not yet existed
299 * in the list, then advance the pointer and add the
300 * next channel on next position
301 * if the check fails the pointer is not advanced and
302 * the channel will not be added and the next channel
303 * will overwrite the current channel.
304 */
305 parray++;
306
307 /* check if list is full */
308 if (++i >= size)
309 break;
310 }
311 /* check if any bits are left */
312 if ((ByteValue & LeftMask) EQ 0)
313 break;
314 }
315 } /* for all bits in byte */
316 } /* if Byte NEQ 0 */
317 } /* for all Bytes in List */
318
319
320 /*
321 * If CHANNEL_0 is included in the list
322 * it has to be changed from CHANNEL_0_INTERNAL to CHANNEL_0
323 * and then the zero_at_start flag is handled.
324 *
325 * If CHANNEL_0 is in the list it is always
326 * at the end of the list.
327 */
328 if(i NEQ start_index AND
329 *(parray-1) EQ CHANNEL_0_INTERNAL)
330 {
331 *(parray-1) = CHANNEL_0;
332
333 if(zero_at_start AND (i > 1))
334 {
335 memmove(&channel_array[1], &channel_array[0], (int)sizeof(channel_array[0])*(i-1));
336 channel_array[0] = CHANNEL_0;
337 }
338 }
339
340 /*
341 * add the end identifier to the output list
342 */
343 if (i<size)
344 {
345 *parray = NOT_PRESENT_16BIT;
346 }
347
348 return i;
349 }
350
351 /*
352 +--------------------------------------------------------------------+
353 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
354 | STATE : code ROUTINE : srv_is_not_in_list |
355 +--------------------------------------------------------------------+
356
357 PURPOSE : Checks if the given channel number is a member of the given
358 list.
359
360 Parameters:
361 channels - contains the existing output list.
362 new_channel - is the channel number which shall be checked.
363 size - indicates the length of the list.
364
365 */
366
367 static UBYTE srv_is_not_in_list (USHORT * channels,
368 USHORT new_channel,
369 USHORT size)
370 {
371 USHORT i;
372
373 /*
374 * for all members of the list
375 */
376 for (i=0;i<size;i++)
377 {
378 /*
379 * The end of the list is reached
380 * that means the new channel is not inside.
381 */
382 if (channels[i] EQ NOT_PRESENT_16BIT)
383 return TRUE;
384
385 /*
386 * the channel is inside
387 */
388 if (channels[i] EQ new_channel)
389 return FALSE;
390 }
391
392 return TRUE;
393 }
394
395 /*
396 +--------------------------------------------------------------------+
397 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
398 | STATE : code ROUTINE : srv_clear_list |
399 +--------------------------------------------------------------------+
400
401 PURPOSE : Clears a list by clearing all bits.
402
403 */
404
405 GLOBAL void srv_clear_list (T_LIST * list)
406 {
407 /*
408 * simple algorithm: clear the whole list.
409 */
410 memset (list, 0, sizeof (T_LIST));
411 }
412
413 /*
414 +--------------------------------------------------------------------+
415 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
416 | STATE : code ROUTINE : srv_copy_list |
417 +--------------------------------------------------------------------+
418
419 PURPOSE : Copies a list.
420
421 */
422
423 GLOBAL void srv_copy_list (T_LIST * target_list, T_LIST * source_list,
424 UBYTE size)
425 {
426 memcpy (target_list, source_list, size);
427 }
428
429 /*
430 +--------------------------------------------------------------------+
431 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
432 | STATE : code ROUTINE : srv_compare_list |
433 +--------------------------------------------------------------------+
434
435 PURPOSE : Compares two lists.
436
437 */
438
439 GLOBAL UBYTE srv_compare_list (T_LIST * list1, T_LIST * list2)
440 {
441 return (memcmp (list1, list2, sizeof (T_LIST)) EQ 0);
442 }
443
444 /*
445 +--------------------------------------------------------------------+
446 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
447 | STATE : code ROUTINE : srv_merge_list |
448 +--------------------------------------------------------------------+
449
450 PURPOSE : Merges two lists. Both lists are bitmaps. So the merge
451 is done by a bitwise OR.
452
453 */
454
455 GLOBAL void srv_merge_list (T_LIST * target_list, T_LIST * list)
456 {
457 USHORT i;
458
459 /*
460 * The maximum list size is T_LIST_MAX_SIZE Bytes for the dualband extended
461 * frequency standard.
462 */
463
464 for (i=0;i<T_LIST_MAX_SIZE;i++)
465 target_list->channels[i] |= list->channels[i];
466 }
467
468 /*
469 +--------------------------------------------------------------------+
470 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
471 | STATE : code ROUTINE : srv_unmask_list |
472 +--------------------------------------------------------------------+
473
474 PURPOSE : This routine resets those bits in destination list that are set in
475 the source list.
476 Refer Cell Selection Improvements-LLD section:4.1.1.3.11
477 */
478
479 GLOBAL void srv_unmask_list(T_LIST *target,T_LIST *source)
480 {
481 UBYTE count=0;
482 for (count=0;count<T_LIST_MAX_SIZE; count++)
483 {
484 target->channels[count] &= ~source->channels[count];
485 }
486 }
487
488
489 /*
490 +--------------------------------------------------------------------+
491 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
492 | STATE : code ROUTINE : srv_trace_freq_in_list |
493 +--------------------------------------------------------------------+
494
495 PURPOSE : This routine traces the frequencies in the list
496 CSI-LLD section:4.1.1.3.11
497 */
498
499 GLOBAL void srv_trace_freq_in_list(T_LIST *list)
500 {
501 U16 i;
502
503 for(i=CHANNEL_0;i<CHANNEL_0_INTERNAL;i++)
504 {
505 if(srv_get_channel (list, i))
506 {
507 TRACE_EVENT_P1("arfcn=%u",i);
508 }
509 }
510 }
511
512 /*
513 +--------------------------------------------------------------------+
514 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
515 | STATE : code ROUTINE : srv_count_list |
516 +--------------------------------------------------------------------+
517
518 PURPOSE : This routine returns the count of the number of channels
519 set in the List
520 CSI-LLD section:4.1.1.3.11
521 */
522
523 GLOBAL U16 srv_count_list(T_LIST *list)
524 {
525 U16 i;
526 U16 sum = 0;
527
528 for(i=CHANNEL_0;i<CHANNEL_0_INTERNAL;i++)
529 {
530 if(srv_get_channel (list, i))
531 {
532 sum++;
533 }
534 }
535
536 return sum;
537 }
538
539 /*
540 +--------------------------------------------------------------------+
541 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
542 | STATE : code ROUTINE : srv_is_list_set |
543 +--------------------------------------------------------------------+
544
545 PURPOSE : This routine checks if any channel in the list is set
546 CSI-LLD section:4.1.1.3.11
547 */
548
549 GLOBAL BOOL srv_is_list_set(T_LIST *list)
550 {
551 U8 i;
552
553 for(i=0;i<T_LIST_MAX_SIZE;i++)
554 {
555 if(list->channels[i])
556 {
557 return TRUE;
558 }
559 }
560
561 return FALSE;
562 }
563
564 /*
565 +--------------------------------------------------------------------+
566 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
567 | STATE : code ROUTINE : srv_get_region_from_std |
568 +--------------------------------------------------------------------+
569
570 PURPOSE : This routine derived "region" from "std"
571 CSI-LLD section:4.1.1.3.11
572 */
573 GLOBAL U8 srv_get_region_from_std(U8 std)
574 {
575 #ifdef TI_PS_FF_QUAD_BAND_SUPPORT
576 U8 region = BOTH_REGIONS;
577 #else
578 U8 region = EUROPEAN_REGION;
579 #endif
580
581 switch(std)
582 {
583 case STD_850:
584 case STD_1900:
585 case STD_DUAL_US:
586 region = AMERICAN_REGION;
587 break;
588 #ifdef TI_PS_FF_QUAD_BAND_SUPPORT
589 case STD_900:
590 case STD_1800:
591 case STD_DUAL:
592 case STD_DUAL_EGSM:
593 region = EUROPEAN_REGION;
594 break;
595 default:
596 TRACE_EVENT_P1 ("srv_get_region_from_std: wrong std %x", std);
597 TRACE_ERROR ("srv_get_region_from_std: wrong std");
598 break;
599 #endif
600 }
601
602 return region;
603 }
604
605 /*
606 +--------------------------------------------------------------------+
607 | PROJECT : GSM-PS (6147) MODULE : RR_SRV |
608 | STATE : code ROUTINE : srv_get_region_from_std_arfcn|
609 +--------------------------------------------------------------------+
610
611 PURPOSE : This routine derived "region" from "std" and "ARFCN"
612 */
613 #ifdef TI_PS_FF_QUAD_BAND_SUPPORT
614 GLOBAL U8 srv_get_region_from_std_arfcn(U8 std, U16 arfcn)
615 {
616 U8 region = EUROPEAN_REGION;
617
618 switch(std)
619 {
620 case STD_850_1800:
621 case STD_850_900_1800:
622 if (INRANGE(LOW_CHANNEL_850,arfcn,HIGH_CHANNEL_850))
623 region = AMERICAN_REGION;
624 else
625 region = EUROPEAN_REGION;
626 break;
627
628 case STD_900_1900:
629 if (INRANGE(LOW_CHANNEL_1900,arfcn,HIGH_CHANNEL_1900))
630 region = AMERICAN_REGION;
631 else
632 region = EUROPEAN_REGION;
633 break;
634
635 case STD_850_900_1900:
636 if (INRANGE(LOW_CHANNEL_1900,arfcn,HIGH_CHANNEL_1900) OR
637 INRANGE(LOW_CHANNEL_850,arfcn,HIGH_CHANNEL_850))
638 region = AMERICAN_REGION;
639 else
640 region = EUROPEAN_REGION;
641 break;
642 default:
643 TRACE_EVENT_P1 ("srv_get_region_from_std_arfcn: wrong std %x", std);
644 TRACE_ERROR ("srv_get_region_from_std_arfcn: wrong std");
645 break;
646 }
647
648 return region;
649 }
650 #endif
651
652 #endif /* !CL_LIST_C */
653