comparison gsm-fw/comlib/cl_list.c @ 664:d36f647c2432

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