diff options
author | Philipp Maier <pmaier@sysmocom.de> | 2019-10-09 13:38:38 +0200 |
---|---|---|
committer | laforge <laforge@osmocom.org> | 2019-10-28 19:43:14 +0000 |
commit | 69e00ccd6ff3a19b771070b78ed3d85dd219799f (patch) | |
tree | bf4914255ba3a4491423bd7e06f8f4efda1953ef /src | |
parent | a0c8195ad37292ab800a6c777fc28383995b4b64 (diff) |
gsm0508: add functions to calculate beginning of a block
The calculation of the beginning of a block for TCH/F, TCH/H and FACCH
can be challenging since those channels are affected by the diagonal
interleaving of the TCH channels. However, GSM 05.02 Section 7 Table 1
of 5 specifies how the blocks are distributed over the TDMA frame
interval. Lets add a mapping function that is based on that table
Related: OS#3803
Change-Id: I3d71c66f8c401f5afbad9b1c86c24580dab9e0ce
Diffstat (limited to 'src')
-rw-r--r-- | src/gsm/gsm0502.c | 157 | ||||
-rw-r--r-- | src/gsm/libosmogsm.map | 1 |
2 files changed, 158 insertions, 0 deletions
diff --git a/src/gsm/gsm0502.c b/src/gsm/gsm0502.c index 53259a42..1a71e617 100644 --- a/src/gsm/gsm0502.c +++ b/src/gsm/gsm0502.c @@ -27,6 +27,9 @@ #include <osmocom/gsm/gsm0502.h> #include <osmocom/gsm/gsm48.h> #include <osmocom/gsm/rsl.h> +#include <osmocom/gsm/gsm_utils.h> +#include <osmocom/core/logging.h> +#include <inttypes.h> unsigned int gsm0502_calc_paging_group(struct gsm48_control_channel_descr *chan_desc, uint64_t imsi) @@ -44,3 +47,157 @@ gsm0502_calc_paging_group(struct gsm48_control_channel_descr *chan_desc, uint64_ return group; } + +/* Clause 7 Table 1 of 5 Mapping of logical channels onto physical channels */ +#define TCH_REPEAT_LENGTH 13 +#define FACCH_F_REPEAT_LENGTH 13 +#define FACCH_H_REPEAT_LENGTH 26 + +static const uint8_t gsm0502_tch_f_traffic_block_map[3][8] = { + {0, 1, 2, 3, 4, 5, 6, 7}, + {4, 5, 6, 7, 8, 9, 10, 11}, + {8, 9, 10, 11, 0, 1, 2, 3} +}; + +static const uint8_t gsm0502_tch_h0_traffic_block_map[3][4] = { + {0, 2, 4, 6}, + {4, 6, 8, 10}, + {8, 10, 0, 2} +}; + +static const uint8_t gsm0502_tch_h1_traffic_block_map[3][4] = { + {1, 3, 5, 7}, + {5, 7, 9, 11}, + {9, 11, 1, 3} +}; + +static const uint8_t gsm0502_tch_f_facch_block_map[3][8] = { + {0, 1, 2, 3, 4, 5, 6, 7}, + {4, 5, 6, 7, 8, 9, 10, 11}, + {8, 9, 10, 11, 0, 1, 2, 3} +}; + +static const uint8_t gsm0502_tch_h0_facch_block_map[3][6] = { + {0, 2, 4, 6, 8, 10}, + {8, 10, 13, 15, 17, 19}, + {17, 19, 21, 23, 0, 2} +}; + +static const uint8_t gsm0502_tch_h1_facch_block_map[3][6] = { + {1, 3, 5, 7, 9, 11}, + {9, 11, 14, 16, 18, 20}, + {18, 20, 22, 24, 1, 3} +}; + +/* Struct to describe a remapping function for block frame nbumbers. The member + * blockend describes the ending of a block for which we want to determine the + * beginning frame number. The member distance describes the value we need to + * subtract from the blockend frame number in order to get the beginning of the + * the block. The member cycle describes the Repeat length in TDMA frames we + * are dealing with. For traffic channels this is always 13, for control + * channels it is different. The member len simply defines amount of + * blockendings and distances we store in the remap table */ +struct fn_remap_table { + unsigned int cycle; + unsigned int len; + uint8_t blockend[8]; + uint8_t distance[8]; +}; + +/* Memory to hold the remap tables we will automatically generate on startup */ +static struct fn_remap_table tch_f_remap_table; +static struct fn_remap_table tch_h0_remap_table; +static struct fn_remap_table tch_h1_remap_table; +static struct fn_remap_table facch_f_remap_table; +static struct fn_remap_table facch_h0_remap_table; +static struct fn_remap_table facch_h1_remap_table; +static struct fn_remap_table *fn_remap_table_ptr[FN_REMAP_MAX]; + +/* Generate a remap table from a given block map. A block map lists the block + * layout as defined in GSM 05.02, Clause 7 Table 1 of 5, one block per row. + * Parameters: + * table: name of the remap table to output + * map: traffic block map input + * rows: length of the traffic block map + * cols: witdh of the traffic block map + * repeat: repeat length in TDMA frames (cycle) */ +#define fn_remap_table_from_traffic_block_map(table, map, rows, cols, repeat) \ + for(i=0;i<rows;i++) { \ + table.blockend[i] = map[i][cols-1]; \ + if(map[i][0] <= map[i][cols-1]) \ + table.distance[i] = map[i][cols-1] - map[i][0]; \ + else \ + table.distance[i] = repeat - map[i][0] + map[i][cols-1]; \ + } \ + table.cycle = repeat; \ + table.len = rows; + +/* Automatically generate fn remap tables on startupmake */ +static __attribute__ ((constructor)) +void fn_remap_tables_build(void) +{ + /* Required by macro */ + unsigned int i; + + /* Generate tables */ + fn_remap_table_from_traffic_block_map(tch_f_remap_table, + gsm0502_tch_f_traffic_block_map, 3, 8, + TCH_REPEAT_LENGTH); + fn_remap_table_from_traffic_block_map(tch_h0_remap_table, + gsm0502_tch_h0_traffic_block_map, 3, 4, + TCH_REPEAT_LENGTH); + fn_remap_table_from_traffic_block_map(tch_h1_remap_table, + gsm0502_tch_h1_traffic_block_map, 3, 4, + TCH_REPEAT_LENGTH); + fn_remap_table_from_traffic_block_map(facch_f_remap_table, + gsm0502_tch_f_facch_block_map, 3, 8, + FACCH_F_REPEAT_LENGTH); + fn_remap_table_from_traffic_block_map(facch_h0_remap_table, + gsm0502_tch_h0_facch_block_map, 3, 6, + FACCH_H_REPEAT_LENGTH); + fn_remap_table_from_traffic_block_map(facch_h1_remap_table, + gsm0502_tch_h1_facch_block_map, 3, 6, + FACCH_H_REPEAT_LENGTH); + + fn_remap_table_ptr[FN_REMAP_TCH_F] = &tch_f_remap_table; + fn_remap_table_ptr[FN_REMAP_TCH_H0] = &tch_h0_remap_table; + fn_remap_table_ptr[FN_REMAP_TCH_H1] = &tch_h1_remap_table; + fn_remap_table_ptr[FN_REMAP_FACCH_F] = &facch_f_remap_table; + fn_remap_table_ptr[FN_REMAP_FACCH_H0] = &facch_h0_remap_table; + fn_remap_table_ptr[FN_REMAP_FACCH_H1] = &facch_h1_remap_table; +} + +/*! Calculate the frame number of the beginning of a block. + * \param[in] fn frame number of the block ending. + * \param[in] channel channel type (see also enum fn_remap_channel). + * \returns frame number of the beginning of the block or input frame number if + * remapping was not possible. */ +uint32_t gsm0502_fn_remap(uint32_t fn, enum gsm0502_fn_remap_channel channel) +{ + uint8_t fn_cycle; + uint8_t i; + int sub = -1; + uint32_t fn_map; + struct fn_remap_table *table; + + OSMO_ASSERT(channel < ARRAY_SIZE(fn_remap_table_ptr)); + table = fn_remap_table_ptr[(uint8_t)channel]; + + fn_cycle = fn % table->cycle; + + for (i = 0; i < table->len; i++) { + if (table->blockend[i] == fn_cycle) { + sub = table->distance[i]; + break; + } + } + + if (sub == -1) { + LOGP(DLGLOBAL, LOGL_ERROR, "could not remap frame number!, fn=%"PRIu32"\n", fn); + return fn; + } + + fn_map = (fn + GSM_MAX_FN - sub) % GSM_MAX_FN; + + return fn_map; +} diff --git a/src/gsm/libosmogsm.map b/src/gsm/libosmogsm.map index ea1f759d..724fe5b1 100644 --- a/src/gsm/libosmogsm.map +++ b/src/gsm/libosmogsm.map @@ -107,6 +107,7 @@ gsm0480_gen_return_error; gsm0480_gen_reject; gsm0502_calc_paging_group; +gsm0502_fn_remap; gsm0503_xcch; gsm0503_rach; |