diff options
Diffstat (limited to 'src/egprs_rlc_compression.cpp')
-rw-r--r-- | src/egprs_rlc_compression.cpp | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/src/egprs_rlc_compression.cpp b/src/egprs_rlc_compression.cpp index c1baaa9..cb4c652 100644 --- a/src/egprs_rlc_compression.cpp +++ b/src/egprs_rlc_compression.cpp @@ -72,6 +72,161 @@ void egprs_compress::build_codewords(egprs_compress_node *root, const char *cdwd } } +/* + * Terminating codes for uninterrupted sequences of 0 and 1 up to 64 bit length + * according to TS 44.060 9.1.10 + */ +static const unsigned t4_term[2][64] = { + { + 0b0000110111, + 0b10, + 0b11, + 0b010, + 0b011, + 0b0011, + 0b0010, + 0b00011, + 0b000101, + 0b000100, + 0b0000100, + 0b0000101, + 0b0000111, + 0b00000100, + 0b00000111, + 0b000011000, + 0b0000010111, + 0b0000011000, + 0b0000001000, + 0b00001100111, + 0b00001101000, + 0b00001101100, + 0b000000101100, + 0b000001011010, + 0b000001100110, + 0b000001100111 + }, + { + 0b00110101, + 0b000111, + 0b0111, + 0b1000, + 0b1011, + 0b1100, + 0b1110, + 0b1111, + 0b10011, + 0b10100, + 0b00111, + 0b01000, + 0b001000, + 0b000011, + 0b110100, + 0b110101, + 0b101010, + 0b101011, + 0b0100111, + 0b0001100, + 0b0001000, + 0b0010111, + 0b0000011, + 0b0000100, + 0b0101000, + 0b0101011, + 0b0010011, + 0b0100100, + 0b0011000, + 0b00000010, + 0b00000011, + 0b00011010, + 0b00011011, + 0b00010010, + 0b00010011, + 0b00010100, + 0b00010101, + 0b00010110, + 0b00010111, + 0b00101000, + 0b00101001, + 0b00101010, + 0b00101011, + 0b00101100, + 0b00101101, + 0b00000100, + 0b00000101, + 0b00001010, + 0b00001011, + 0b01010010, + 0b01010011, + 0b01010100, + 0b01010101, + 0b00100100, + 0b00100101, + 0b01011000, + 0b01011001, + 0b01011010, + 0b01011011, + 0b01001010, + 0b01001011, + 0b00110010, + 0b00110011, + 0b00110100 + } +}; +static const unsigned t4_term_length[2][64] = { + {10, 2, 2, 3, 3, 4, 4, 5, 6, 6, 7, 7, 7, 8, 8, 9, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12}, + {8, 6, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8} +}; + +static const unsigned t4_min_term_length[] = {2, 4}; +static const unsigned t4_min_make_up_length[] = {10, 5}; + +static const unsigned t4_max_term_length[] = {12, 8}; +static const unsigned t4_max_make_up_length[] = {13, 9}; + +static const unsigned t4_make_up_length[2][15] = { + {10, 12, 12, 12, 12, 12, 12, 13, 13, 13, 13, 13, 13, 13, 13}, + {5, 5, 6, 7, 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, 9} +}; + +static const unsigned t4_make_up_ind[15] = {64, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960}; + +static const unsigned t4_make_up[2][15] = { + { + 0b0000001111, + 0b000011001000, + 0b000011001001, + 0b000001011011, + 0b000000110011, + 0b000000110100, + 0b000000110101, + 0b0000001101100, + 0b0000001101101, + 0b0000001001010, + 0b0000001001011, + 0b0000001001100, + 0b0000001001101, + 0b0000001110010, + 0b0000001110011 + }, + { + 0b11011, + 0b10010, + 0b010111, + 0b0110111, + 0b00110110, + 0b00110111, + 0b01100100, + 0b01100101, + 0b01101000, + 0b01100111, + 0b011001100, + 0b011001101, + 0b011010010, + 0b011010011, + 0b011010100 + } +}; + /* The code words for one run length and zero * run length are described in table 9.1.10.1 * of 3gpp 44.060 @@ -342,3 +497,134 @@ void egprs_compress::decode_tree_init() build_codewords(ones_list, one_run_len_code_list); build_codewords(zeros_list, zero_run_len_code_list); } +void compress_bitmap( + uint16_t *run_len_cnt, /* cnt: run length count */ + uint16_t *codewrd_bitmap, /* code word */ + int16_t *codewrd_len, /* number of bits in the code word */ + bitvec *crbb_vec, /* bitmap buffer to put code word in */ + uint8_t clr_code) +{ + int i = 0; + unsigned writeIndex = crbb_vec->cur_bit; + + *codewrd_bitmap = 0; + *codewrd_len = 0; + if ((*run_len_cnt) >= 64) { + for (i = 0; i < 15; i++) { + if (t4_make_up_ind[i] == *run_len_cnt) { + *codewrd_bitmap = t4_make_up[clr_code][i]; + *codewrd_len = t4_make_up_length[clr_code][i]; + } + } + } else { + *codewrd_bitmap = t4_term[clr_code][*run_len_cnt]; + *codewrd_len = t4_term_length[clr_code][*run_len_cnt]; + } + bitvec_write_field(crbb_vec, writeIndex, (*codewrd_bitmap), (*codewrd_len)); +} + +int osmo_t4_compress(struct bitvec *bv) +{ + uint8_t crbb_len = 0; + uint8_t uclen_crbb = 0; + uint8_t crbb_bitmap[127] = {'\0'}; + uint8_t color_code = (bv->data[0] & 0x80)>>7; + struct bitvec crbb_vec; + + crbb_vec.data = crbb_bitmap; + crbb_vec.cur_bit = 0; + crbb_vec.data_len = 127; + bv->data_len = bv->cur_bit; + bv->cur_bit = 0; + if (compress_rbb(bv, &crbb_vec, &uclen_crbb, 23*8)) { + memcpy(bv->data, crbb_bitmap, (crbb_len+7)/8); + bv->cur_bit = crbb_len; + bv->data_len = (crbb_len+7)/8; + return color_code; + } + else + printf("Encode faled\n"); + return -1; +} + +/*! \brief compression algorithm using T4 encoding + * the compressed bitmap's are copied in crbb_bitmap + * \param[in] rbb_vec bit vector to be encoded + * \return 1 if compression is success or 0 for failure + */ +int compress_rbb( + struct bitvec *urbb_vec, + struct bitvec *crbb_vec, + uint8_t *uclen_crbb, /* Uncompressed bitmap len in CRBB */ + uint8_t max_bits) /* max remaining bits */ +{ + bool run_len_bit; + int buflen = urbb_vec->cur_bit; + int total_bits = urbb_vec->cur_bit; + uint16_t rlen; + uint16_t temprl = 0; + uint16_t cbmap = 0; /* Compressed code word */ + int16_t nbits; /* Length of code word */ + uint16_t uclen = 0; + int16_t clen = 0; + uint8_t clr_code = 0; + + urbb_vec->cur_bit = 0; + run_len_bit = (urbb_vec->data[0] & 0x80)>>7; + while (buflen > 0) { + temprl = 0; + /* Find Run length */ + if (run_len_bit == 1) + rlen = bitvec_rl_curbit(urbb_vec, true, total_bits); + else + rlen = bitvec_rl_curbit(urbb_vec, false, total_bits); + buflen = buflen - rlen; + /* if rlen> 64 need 2 code words */ + /*Compress the bits */ + if (run_len_bit == 0) { + clr_code = 0; + if (rlen >= 64) { + temprl = (rlen/64)*64; + compress_bitmap(&temprl, &cbmap, &nbits, + crbb_vec, clr_code); + clen = clen + nbits; + } + temprl = MOD64(rlen); + compress_bitmap(&temprl, &cbmap, &nbits, + crbb_vec, clr_code); + /* next time the run length will be Ones */ + run_len_bit = 1; + } else { + clr_code = 1; + if (rlen >= 64) { + temprl = (rlen/64)*64; + compress_bitmap(&temprl, &cbmap, &nbits, + crbb_vec, clr_code); + clen = clen + nbits; + } + temprl = MOD64(rlen); + compress_bitmap(&temprl, &cbmap, &nbits, + crbb_vec, clr_code); + + /* next time the run length will be Zeros */ + run_len_bit = 0; + } + uclen = uclen + (rlen); + clen = clen + nbits; + /*compressed bitmap exceeds the buffer space */ + if (clen > max_bits) { + uclen = uclen - rlen; + clen = clen - nbits; + break; + } + } + crbb_vec->cur_bit = clen; + *uclen_crbb = uclen; + if (clen >= uclen) + /* No Gain is observed, So no need to compress */ + return 0; + else + /* Add compressed bitmap to final buffer */ + return 1; +} + |