📄 metrics.c
字号:
/* | | Copyright disclaimer: | This software was developed at the National Institute of Standards | and Technology by employees of the Federal Government in the course | of their official duties. Pursuant to title 17 Section 105 of the | United States Code this software is not subject to copyright | protection and is in the public domain. | | We would appreciate acknowledgement if the software is used. |*//* | Project: WCDMA simulation environment | Module: Viterbi path metric calculation. | Author: Tommi Makelainen, NIST | Date: January 11, 1999 | | History: | January 11, 1999 Tommi Makelainen | Initial version. | | February 16, 1999 Tommi Makelainen | Corrected branch metric calculation for soft | bits. | */#include <stdio.h>#include <stdlib.h>#include <math.h>#include "metrics.h" /* --------------------------------------------------------------- *//* * Function: MetricTable_R1o3_Init * Desc.: Metric table initialization for Viterbi algorithm. * Constrain length K=9 and coding rate 1/3 are fixed. * * Note: * 'no_of_probabilities' can get max value of 8. */void MetricTable_R1o3_Init( MetricTable* this, enum metric_type_type metric_type, double bit_probabilities_0[], double bit_probabilities_1[], int no_of_probabilities){ int i, bit; double temp; this->Metric_Type = metric_type; if(metric_type == HAMMING_METRIC) { this->Metric_Table[0][0] = 0.0; this->Metric_Table[1][0] = -1.0; this->Metric_Table[2][0] = -1.0; this->Metric_Table[3][0] = -2.0; this->Metric_Table[4][0] = -1.0; this->Metric_Table[5][0] = -2.0; this->Metric_Table[6][0] = -2.0; this->Metric_Table[7][0] = -3.0; this->Metric_Table[0][1] = -1.0; this->Metric_Table[1][1] = 0.0; this->Metric_Table[2][1] = -2.0; this->Metric_Table[3][1] = -1.0; this->Metric_Table[4][1] = -2.0; this->Metric_Table[5][1] = -1.0; this->Metric_Table[6][1] = -3.0; this->Metric_Table[7][1] = -2.0; this->Metric_Table[0][2] = -1.0; this->Metric_Table[1][2] = -2.0; this->Metric_Table[2][2] = 0.0; this->Metric_Table[3][2] = -1.0; this->Metric_Table[4][2] = -2.0; this->Metric_Table[5][2] = -3.0; this->Metric_Table[6][2] = -1.0; this->Metric_Table[7][2] = -2.0; this->Metric_Table[0][3] = -2.0; this->Metric_Table[1][3] = -1.0; this->Metric_Table[2][3] = -1.0; this->Metric_Table[3][3] = 0.0; this->Metric_Table[4][3] = -3.0; this->Metric_Table[5][3] = -2.0; this->Metric_Table[6][3] = -2.0; this->Metric_Table[7][3] = -1.0; this->Metric_Table[0][4] = -1.0; this->Metric_Table[1][4] = -2.0; this->Metric_Table[2][4] = -2.0; this->Metric_Table[3][4] = -3.0; this->Metric_Table[4][4] = 0.0; this->Metric_Table[5][4] = -1.0; this->Metric_Table[6][4] = -1.0; this->Metric_Table[7][4] = -2.0; this->Metric_Table[0][5] = -2.0; this->Metric_Table[1][5] = -1.0; this->Metric_Table[2][5] = -3.0; this->Metric_Table[3][5] = -2.0; this->Metric_Table[4][5] = -1.0; this->Metric_Table[5][5] = 0.0; this->Metric_Table[6][5] = -2.0; this->Metric_Table[7][5] = -1.0; this->Metric_Table[0][6] = -2.0; this->Metric_Table[1][6] = -3.0; this->Metric_Table[2][6] = -2.0; this->Metric_Table[3][6] = -2.0; this->Metric_Table[4][6] = -1.0; this->Metric_Table[5][6] = -2.0; this->Metric_Table[6][6] = 0.0; this->Metric_Table[7][6] = -1.0; this->Metric_Table[0][7] = -3.0; this->Metric_Table[1][7] = -2.0; this->Metric_Table[2][7] = -2.0; this->Metric_Table[3][7] = -1.0; this->Metric_Table[4][7] = -2.0; this->Metric_Table[5][7] = -1.0; this->Metric_Table[6][7] = -1.0; this->Metric_Table[7][7] = 0.0; return; } if (metric_type == SOFT_METRIC) { /* * Convert bit probabilities for soft metrics to suitable branch * metric values. * branch_metric = 2 * log2( p(rx_symbol|tx_symbol) - 0.05) * Channel can be also non-symmetric, so the probabilities for 0 * and 1 can be different. */ for (i=0; i < no_of_probabilities; i++) { if (bit_probabilities_0[i] < 0.1) { this->Metric_Table[i][0] = -8.0; } else { this->Metric_Table[i][0] = 0 - floor(abs(2 * log(bit_probabilities_0[i] - 0.1 + 0.05))); } } for (i=0; i < no_of_probabilities; i++) { if (bit_probabilities_1[i] < 0.1) { this->Metric_Table[i][1] = -8.0; } else { this->Metric_Table[i][1] = 0 - floor(abs(2 * log(bit_probabilities_1[i] - 0.1 + 0.05))); } }#ifdef WCDMA_DEBUG_OUTPUT printf("\nSoft probability branch metrices: \n"); for (i=0; i < no_of_probabilities; i++) { printf("[%d][0] = %g, [%d][1] = %g \n", i, this->Metric_Table[i][0], i, this->Metric_Table[i][1]); } /* for */ printf("\n");#endif /* WCDMA_DEBUG_OUTPUT */ return; } printf("invalid metric type passed to metric builder\n"); return; }/* --------------------------------------------------------------- *//* * Function: MetricTable_R1o2_Init * Desc.: Metric table initialization for Viterbi algorithm. * Constrain length K=9 and coding rate 1/2 are fixed. * * Note: * 'no_of_probabilities' can get max value of 8. */void MetricTable_R1o2_Init( MetricTable* this, enum metric_type_type metric_type, double bit_probabilities_0[], double bit_probabilities_1[], int no_of_probabilities){ int i, bit; double temp; this->Metric_Type = metric_type; if(metric_type == HAMMING_METRIC) { this->Metric_Table[0][0] = 0.0; this->Metric_Table[1][0] = -1.0; this->Metric_Table[2][0] = -1.0; this->Metric_Table[3][0] = -2.0; this->Metric_Table[0][1] = -1.0; this->Metric_Table[1][1] = 0.0; this->Metric_Table[2][1] = -2.0; this->Metric_Table[3][1] = -1.0; this->Metric_Table[0][2] = -1.0; this->Metric_Table[1][2] = -2.0; this->Metric_Table[2][2] = 0.0; this->Metric_Table[3][2] = -1.0; this->Metric_Table[0][3] = -2.0; this->Metric_Table[1][3] = -1.0; this->Metric_Table[2][3] = -1.0; this->Metric_Table[3][3] = 0.0; return; } if (metric_type == SOFT_METRIC) { /* * Convert bit probabilities for soft metrics to suitable branch * metric values. * branch_metric = 2 * log2( p(rx_symbol|tx_symbol) - 0.05) * Channel can be also non-symmetric, so the probabilities for 0 * and 1 can be different. */ for (i=0; i < no_of_probabilities; i++) { if (bit_probabilities_0[i] < 0.1) { this->Metric_Table[i][0] = -8.0; } else { this->Metric_Table[i][0] = 0 - floor(abs(2 * log(bit_probabilities_0[i] - 0.1 + 0.05))); } } for (i=0; i < no_of_probabilities; i++) { if (bit_probabilities_1[i] < 0.1) { this->Metric_Table[i][1] = -8.0; } else { this->Metric_Table[i][1] = 0 - floor(abs(2 * log(bit_probabilities_1[i] - 0.1 + 0.05))); } }#ifdef WCDMA_DEBUG_OUTPUT printf("\nSoft probability branch metrices: \n"); for (i=0; i < no_of_probabilities; i++) { printf("[%d][0] = %g, [%d][1] = %g \n", i, this->Metric_Table[i][0], i, this->Metric_Table[i][1]); } /* for */ printf("\n");#endif /* WCDMA_DEBUG_OUTPUT */ return; } printf("invalid metric type passed to metric builder\n"); return; }/* --------------------------------------------------------------- *//* * Function: MetricTable_R1o3_SoftSymbolMetric * Desc.: Soft metric calculation. The metric is calculated * as an euclidean distance between tx and rx symbols. * * Note: */double MetricTable_R1o3_SoftSymbolMetric( MetricTable* this, int rx_symbol, int tx_symbol) { int rx_bit1, rx_bit2, rx_bit3, tx_bit1, tx_bit2, tx_bit3; double metric_val; /* * Decompose rx_symbol into bits */ rx_bit1 = (rx_symbol >> 2) & 0x1; rx_bit2 = (rx_symbol >> 1) & 0x1; rx_bit3 = rx_symbol & 0x1; /* * Decompose tx_symbol into bits */ tx_bit1 = (tx_symbol >> 2) & 0x1; tx_bit2 = (tx_symbol >> 1) & 0x1; tx_bit3 = tx_symbol & 0x1; /* * Look up bit metrics and add them together */ metric_val = this->Metric_Table[rx_bit1][tx_bit1] + this->Metric_Table[rx_bit2][tx_bit2] + this->Metric_Table[rx_bit3][tx_bit3]; return(metric_val);};/* --------------------------------------------------------------- *//* * Function: MetricTable_R1o2_SoftSymbolMetric * Desc.: Soft metric calculation. The metric is calculated * as an euclidean distance between tx and rx symbols. * * Note: */double MetricTable_R1o2_SoftSymbolMetric( MetricTable* this, int rx_symbol, int tx_symbol) { int rx_bit1, rx_bit2, tx_bit1, tx_bit2; double metric_val; /* * Decompose rx_symbol into bits */ rx_bit1 = (rx_symbol >> 1) & 0x1; rx_bit2 = rx_symbol & 0x1; /* * Decompose tx_symbol into bits */ tx_bit1 = (tx_symbol >> 1) & 0x1; tx_bit2 = tx_symbol & 0x1; /* * Look up bit metrics and add them together */ metric_val = this->Metric_Table[rx_bit1][tx_bit1] + this->Metric_Table[rx_bit2][tx_bit2]; return(metric_val);};/* --------------------------------------------------------------- *//* * Function: MetricTable_R1o2_GetBranchMetric * Desc.: Returns a branch metric value for a given tx and rx * symbols. * * Note: */double MetricTable_R1o2_GetBranchMetric( MetricTable* this, int rx_symbol, double soft_metric, int tx_symbol) { if(this->Metric_Type == SOFT_METRIC) { return( /* soft_metric * */ MetricTable_R1o2_SoftSymbolMetric(this, rx_symbol, tx_symbol) ); } else { return(this->Metric_Table[rx_symbol][tx_symbol]); }}; /* --------------------------------------------------------------- *//* * Function: MetricTable_R1o3_GetBranchMetric * Desc.: Returns a branch metric value for a given tx and rx * symbols. * * Note: */double MetricTable_R1o3_GetBranchMetric( MetricTable* this, int rx_symbol, double soft_metric, int tx_symbol) { if(this->Metric_Type == SOFT_METRIC) { return( /* soft_metric * */ MetricTable_R1o3_SoftSymbolMetric(this, rx_symbol, tx_symbol) ); } else { return(this->Metric_Table[rx_symbol][tx_symbol]); }}; /* --------------------------------------------------------------- */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -