[PATCH 8/9] si: Add generic range w(k) encoder

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/OpenBSC@lists.osmocom.org/.

Jacob Erlbeck jerlbeck at sysmocom.de
Tue Jan 14 13:24:22 UTC 2014


Currently the encoding of the chan_list is done by a hard-coded
sequence of macros that closely resembles figure 10.5.16 in
3GPP TS 04.08.

This patch replaces this by an algorithmic solution that can be used
for all range encodings and is based on the property

    W(2^i) to W(2^(i+1)-1) are on w1_len-i bits when present

(see section 10.5.2.13 in TS 04.08).

Ticket: OW#1061
Sponsored-by: On-Waves ehf
---
 openbsc/src/libbsc/arfcn_range_encode.c |  141 ++++++++++++++++++-------------
 1 file changed, 83 insertions(+), 58 deletions(-)

diff --git a/openbsc/src/libbsc/arfcn_range_encode.c b/openbsc/src/libbsc/arfcn_range_encode.c
index 17c347f..3e5b1fc 100644
--- a/openbsc/src/libbsc/arfcn_range_encode.c
+++ b/openbsc/src/libbsc/arfcn_range_encode.c
@@ -178,16 +178,6 @@ int range_enc_determine_range(const int *arfcns, const int size, int *f0)
 	return ARFCN_RANGE_INVALID;
 }
 
-/*
- * The below is easier is to write in four methods than
- * to use the max_bits. The encoding is so screwed.. as
- * the bits need to be put in place in the wrong order..
- */
-#define HIGH_BITS(w, index, bits, offset) \
-		(w[index - 1] >> (bits - offset))
-#define LOW_BITS(w, index, bits, offset) \
-		(w[index - 1])
-
 static void write_orig_arfcn(uint8_t *chan_list, int f0)
 {
 	chan_list[0] |= (f0 >> 9) & 1;
@@ -195,6 +185,88 @@ static void write_orig_arfcn(uint8_t *chan_list, int f0)
 	chan_list[2] = (f0 & 1) << 7;
 }
 
+static void write_all_wn(uint8_t *chan_list, int bit_offs,
+			 int *w, int w_size, int w1_len)
+{
+	int octet_offs = 0; /* offset into chan_list */
+	int wk_len = w1_len; /* encoding size in bits of w[k] */
+	int k; /* 1 based */
+	int level = 0; /* tree level, top level = 0 */
+	int lvl_left = 1; /* nodes per tree level */
+
+	/* W(2^i) to W(2^(i+1)-1) are on w1_len-i bits when present */
+
+	for (k = 1; k <= w_size; k++) {
+		int wk_left = wk_len;
+		DEBUGP(DRR,
+		       "k=%d, wk_len=%d, offs=%d:%d, level=%d, "
+		       "lvl_left=%d\n",
+		       k, wk_len, octet_offs, bit_offs, level, lvl_left);
+
+		while (wk_left > 0) {
+			int cur_bits = 8 - bit_offs;
+			int cur_mask;
+			int wk_slice;
+
+			if (cur_bits > wk_left)
+				cur_bits = wk_left;
+
+			cur_mask = ((1 << cur_bits) - 1);
+
+			DEBUGP(DRR,
+			       " wk_left=%d, cur_bits=%d, offs=%d:%d\n",
+			       wk_left, cur_bits, octet_offs, bit_offs);
+
+			/* advance */
+			wk_left -= cur_bits;
+			bit_offs += cur_bits;
+
+			/* right aligned wk data for current out octet */
+			wk_slice = (w[k-1] >> wk_left) & cur_mask;
+
+			/* cur_bits now contains the number of bits
+			 * that are to be copied from wk to the chan_list.
+			 * wk_left is set to the number of bits that must
+			 * not yet be copied.
+			 * bit_offs points after the bit area that is going to
+			 * be overwritten:
+			 *
+			 *          wk_left
+			 *             |
+			 *             v
+			 * wk: WWWWWWWWWWW
+			 *        |||||<-- wk_slice, cur_bits=5
+			 *      --WWWWW-
+			 *             ^
+			 *             |
+			 *           bit_offs
+			 */
+
+			DEBUGP(DRR,
+			       " wk=%02x, slice=%02x/%02x, cl=%02x\n",
+			       w[k-1], wk_slice, cur_mask, wk_slice << (8 - bit_offs));
+
+			chan_list[octet_offs] &= ~(cur_mask << (8 - bit_offs));
+			chan_list[octet_offs] |= wk_slice << (8 - bit_offs);
+
+			/* adjust output */
+			if (bit_offs == 8) {
+				bit_offs = 0;
+				octet_offs += 1;
+			}
+		}
+
+		/* adjust bit sizes */
+		lvl_left -= 1;
+		if (!lvl_left) {
+			/* completed tree level, advance to next */
+			level += 1;
+			lvl_left = 1 << level;
+			wk_len -= 1;
+		}
+	}
+}
+
 int range_enc_range128(uint8_t *chan_list, int f0, int *w)
 {
 	chan_list[0] = 0x8C;
@@ -215,57 +287,10 @@ int range_enc_range256(uint8_t *chan_list, int f0, int *w)
 
 int range_enc_range512(uint8_t *chan_list, int f0, int *w)
 {
-	struct gsm48_range_512 *range512;
 	chan_list[0] = 0x88;
 	write_orig_arfcn(chan_list, f0);
 
-	range512 = (struct gsm48_range_512 *) &chan_list[0];
-
-	/* W(1) */
-	range512->w1_hi = HIGH_BITS(w, 1, 9, 7);
-	range512->w1_lo = LOW_BITS (w, 1, 9, 2);
-	/* W(2) */
-	range512->w2_hi = HIGH_BITS(w, 2, 8, 6);
-	range512->w2_lo = LOW_BITS (w, 2, 8, 2);
-	/* W(3) */
-	range512->w3_hi = HIGH_BITS(w, 3, 8, 6);
-	range512->w3_lo = LOW_BITS (w, 3, 8, 2);
-	/* W(4) */
-	range512->w4_hi = HIGH_BITS(w, 4, 7, 6);
-	range512->w4_lo = LOW_BITS (w, 4, 7, 1);
-	/* W(5) */
-	range512->w5 = HIGH_BITS(w, 5, 7, 7);
-	/* W(6) */
-	range512->w6 = HIGH_BITS(w, 6, 7, 7);
-	/* W(7) */
-	range512->w7_hi = HIGH_BITS(w, 7, 7, 1);
-	range512->w7_lo = LOW_BITS (w, 7, 7, 6);
-	/* W(8) */
-	range512->w8_hi = HIGH_BITS(w, 8, 6, 2);
-	range512->w8_lo = LOW_BITS (w, 8, 6, 4);
-	/* W(9) */
-	range512->w9_hi = HIGH_BITS(w, 9, 6, 4);
-	range512->w9_lo = LOW_BITS(w, 9, 6, 2);
-	/* W(10) */
-	range512->w10 = HIGH_BITS(w, 10, 6, 6);
-	/* W(11) */
-	range512->w11 = HIGH_BITS(w, 11, 6, 6);
-	/* W(12) */
-	range512->w12_hi = HIGH_BITS(w, 12, 6, 2);
-	range512->w12_lo = LOW_BITS (w, 12, 6, 4);
-	/* W(13) */
-	range512->w13_hi = HIGH_BITS(w, 13, 6, 4);
-	range512->w13_lo = LOW_BITS(w, 13, 6, 2);
-	/* W(14) */
-	range512->w14 = HIGH_BITS(w, 14, 6, 6);
-	/* W(15) */
-	range512->w15 = HIGH_BITS(w, 15, 6, 6);
-	/* W(16) */
-	range512->w16_hi = HIGH_BITS(w, 16, 5, 2);
-	range512->w16_lo = LOW_BITS(w, 16, 5, 3);
-	/* W(17) */
-	range512->w17 = HIGH_BITS(w, 17, 5, 5);
-
+	write_all_wn(&chan_list[2], 1, w, 17, 9);
 	return 0;
 }
 
-- 
1.7.9.5





More information about the OpenBSC mailing list