diff options
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; | 
