forked from cellular-infrastructure/osmo-pcu
314 lines
6.3 KiB
C++
314 lines
6.3 KiB
C++
/* egprs_rlc_compression.h
|
|
* Routines for EGPRS RLC bitmap compression handling
|
|
*/
|
|
#include <egprs_rlc_compression.h>
|
|
#include <errno.h>
|
|
#include <decoding.h>
|
|
|
|
egprs_compress *egprs_compress::s_instance = 0;
|
|
Node *egprs_compress::ones_list = NULL;
|
|
Node *egprs_compress::zeros_list = NULL;
|
|
|
|
void egprs_compress::build_codeword(Node *root, const char *cdwd[])
|
|
{
|
|
Node *iter; /* iterate the node on the tree */
|
|
int len; /* length of the code word */
|
|
int i; /* iterater */
|
|
uint16_t idx; /* interate index of the code word table */
|
|
|
|
root->left = NULL;
|
|
root->right = NULL;
|
|
root->run_length = NULL;
|
|
|
|
for (idx = 0; idx < MAX_CDWDTBL_LEN; idx++) {
|
|
len = strlen((const char *)cdwd[idx]);
|
|
iter = root;
|
|
for (i = 0; i < len; i++) {
|
|
if (cdwd[idx][i] == '0') {
|
|
if (iter->left == NULL) {
|
|
iter->left = (Node *)malloc(sizeof(Node));
|
|
/* create a clean node */
|
|
iter->left->left = NULL;
|
|
iter->left->right = NULL;
|
|
iter->left->run_length = NULL;
|
|
}
|
|
iter = iter->left;
|
|
} else if (cdwd[idx][i] == '1') {
|
|
if (iter->right == NULL) {
|
|
iter->right = (Node *)malloc(sizeof(Node));
|
|
/* create a clean node */
|
|
iter->right->left = NULL;
|
|
iter->right->right = NULL;
|
|
iter->right->run_length = NULL;
|
|
}
|
|
iter = iter->right;
|
|
}
|
|
}
|
|
if (iter != NULL) {
|
|
iter->run_length = (uint16_t *)malloc(sizeof(uint16_t));
|
|
*(iter->run_length) = (uint16_t)NULL;
|
|
if (idx < 64)
|
|
*(iter->run_length) = idx;
|
|
else
|
|
*(iter->run_length) = (idx - 63) * 64;
|
|
}
|
|
}
|
|
}
|
|
|
|
const char *one_run_len_code_list[MAX_CDWDTBL_LEN] = {
|
|
"00110101",
|
|
"000111",
|
|
"0111",
|
|
"1000",
|
|
"1011",
|
|
"1100",
|
|
"1110",
|
|
"1111",
|
|
"10011",
|
|
"10100",
|
|
"00111",
|
|
"01000",
|
|
"001000",
|
|
"000011",
|
|
"110100",
|
|
"110101",
|
|
"101010",
|
|
"101011",
|
|
"0100111",
|
|
"0001100",
|
|
"0001000",
|
|
"0010111",
|
|
"0000011",
|
|
"0000100",
|
|
"0101000",
|
|
"0101011",
|
|
"0010011",
|
|
"0100100",
|
|
"0011000",
|
|
"00000010",
|
|
"00000011",
|
|
"00011010",
|
|
"00011011",
|
|
"00010010",
|
|
"00010011",
|
|
"00010100",
|
|
"00010101",
|
|
"00010110",
|
|
"00010111",
|
|
"00101000",
|
|
"00101001",
|
|
"00101010",
|
|
"00101011",
|
|
"00101100",
|
|
"00101101",
|
|
"00000100",
|
|
"00000101",
|
|
"00001010",
|
|
"00001011",
|
|
"01010010",
|
|
"01010011",
|
|
"01010100",
|
|
"01010101",
|
|
"00100100",
|
|
"00100101",
|
|
"01011000",
|
|
"01011001",
|
|
"01011010",
|
|
"01011011",
|
|
"01001010",
|
|
"01001011",
|
|
"00110010",
|
|
"00110011",
|
|
"00110100",
|
|
"11011",
|
|
"10010",
|
|
"010111",
|
|
"0110111",
|
|
"00110110",
|
|
"00110111",
|
|
"01100100",
|
|
"01100101",
|
|
"01101000",
|
|
"01100111",
|
|
"011001100",
|
|
"011001101",
|
|
"011010010",
|
|
"011010011",
|
|
"011010100"
|
|
};
|
|
|
|
const char *zero_run_len_code_list[MAX_CDWDTBL_LEN] = {
|
|
"0000110111",
|
|
"10",
|
|
"11",
|
|
"010",
|
|
"011",
|
|
"0011",
|
|
"0010",
|
|
"00011",
|
|
"000101",
|
|
"000100",
|
|
"0000100",
|
|
"0000101",
|
|
"0000111",
|
|
"00000100",
|
|
"00000111",
|
|
"000011000",
|
|
"0000010111",
|
|
"0000011000",
|
|
"0000001000",
|
|
"00001100111",
|
|
"00001101000",
|
|
"00001101100",
|
|
"00000110111",
|
|
"00000101000",
|
|
"00000010111",
|
|
"00000011000",
|
|
"000011001010",
|
|
"000011001011",
|
|
"000011001100",
|
|
"000011001101",
|
|
"000001101000",
|
|
"000001101001",
|
|
"000001101010",
|
|
"000001101011",
|
|
"000011010010",
|
|
"000011010011",
|
|
"000011010100",
|
|
"000011010101",
|
|
"000011010110",
|
|
"000011010111",
|
|
"000001101100",
|
|
"000001101101",
|
|
"000011011010",
|
|
"000011011011",
|
|
"000001010100",
|
|
"000001010101",
|
|
"000001010110",
|
|
"000001010111",
|
|
"000001100100",
|
|
"000001100101",
|
|
"000001010010",
|
|
"000001010011",
|
|
"000000100100",
|
|
"000000110111",
|
|
"000000111000",
|
|
"000000100111",
|
|
"000000101000",
|
|
"000001011000",
|
|
"000001011001",
|
|
"000000101011",
|
|
"000000101100",
|
|
"000001011010",
|
|
"000001100110",
|
|
"000001100111",
|
|
"0000001111",
|
|
"000011001000",
|
|
"000011001001",
|
|
"000001011011",
|
|
"000000110011",
|
|
"000000110100",
|
|
"000000110101",
|
|
"0000001101100",
|
|
"0000001101101",
|
|
"0000001001010",
|
|
"0000001001011",
|
|
"0000001001100",
|
|
"0000001001101",
|
|
"0000001110010",
|
|
"0000001110011"
|
|
};
|
|
|
|
int search_runlen(
|
|
Node *root, /* root of Ones or Zeros tree */
|
|
const uint8_t *bmbuf, /* Received compressed bitmap buf */
|
|
uint8_t bit_pos, /* the start bit pos to read codeword */
|
|
uint8_t *len_codewd, /* length of code word */
|
|
uint16_t *rlen)
|
|
{
|
|
Node *iter;
|
|
uint8_t dir;
|
|
|
|
iter = root;
|
|
*len_codewd = 0;
|
|
|
|
while (iter->run_length == 0) {
|
|
if ((iter->left == NULL) && (iter->right == NULL))
|
|
return -1;
|
|
|
|
/* get the bit value at the bitpos and put it in right most of dir */
|
|
dir = ((bmbuf[BITS_TO_BYTES(bit_pos)-1]
|
|
>>(7-(MOD8(bit_pos)))) & 0x01);
|
|
(bit_pos)++;
|
|
(*len_codewd)++;
|
|
|
|
if (((dir&0x01) == 0) && (iter->left != NULL))
|
|
iter = iter->left;
|
|
|
|
else if (((dir&0x01) == 1) && (iter->right != NULL))
|
|
iter = iter->right;
|
|
else
|
|
return -1;
|
|
}
|
|
(*rlen) = *(iter->run_length);
|
|
|
|
return 1;
|
|
} /* search_runlen */
|
|
|
|
void Decoding::decompress_crbb(
|
|
int8_t compress_bmap_len, /* compressed bitmap length */
|
|
uint8_t clr_code_bit, /* run length of Ones or Zeros */
|
|
const uint8_t *orig_crbb_buf, /* received block crbb bitmap */
|
|
bitvec * dest)
|
|
{
|
|
|
|
uint8_t bit_pos = 0;
|
|
uint8_t nbits = 0; /* number of bits of codeword */
|
|
uint16_t run_length = 0;
|
|
uint16_t cbmaplen = 0; /* compressed bitmap part after decompression */
|
|
unsigned wp = dest->cur_bit;
|
|
egprs_compress *compress = egprs_compress::instance();
|
|
|
|
while (compress_bmap_len > 0) {
|
|
if (clr_code_bit == 1) {
|
|
search_runlen(compress->ones_list, orig_crbb_buf,
|
|
bit_pos, &nbits, &run_length);
|
|
/*If run length > 64, need makeup and terminating code*/
|
|
if (run_length < 64)
|
|
clr_code_bit = 0;
|
|
cbmaplen = cbmaplen + run_length;
|
|
/* put run length of Ones in uncompressed bitmap */
|
|
while (run_length != 0) {
|
|
if (run_length > 8) {
|
|
bitvec_write_field(dest, wp, 0xff, 8);
|
|
run_length = run_length - 8;
|
|
} else {
|
|
bitvec_write_field(dest, wp, 0xff,
|
|
run_length);
|
|
run_length = 0;
|
|
}
|
|
}
|
|
} else {
|
|
search_runlen(compress->zeros_list, orig_crbb_buf,
|
|
bit_pos, &nbits, &run_length);
|
|
/*If run length > 64, need makeup and terminating code*/
|
|
if (run_length < 64)
|
|
clr_code_bit = 1;
|
|
cbmaplen = cbmaplen + run_length;
|
|
/* put run length of Zeros in uncompressed bitmap */
|
|
while (run_length != 0) {
|
|
if (run_length > 8) {
|
|
bitvec_write_field(dest, wp, 0x00, 8);
|
|
run_length = run_length - 8;
|
|
} else {
|
|
bitvec_write_field(dest, wp, 0x00,
|
|
run_length);
|
|
run_length = 0;
|
|
}
|
|
}
|
|
}
|
|
bit_pos = bit_pos + nbits;
|
|
compress_bmap_len = compress_bmap_len - nbits;
|
|
}
|
|
} /* Decompress_CRBB */
|