mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2026-04-19 23:02:43 +00:00
233 lines
5.5 KiB
C
233 lines
5.5 KiB
C
#include "correct/convolutional/bit.h"
|
|
|
|
bit_writer_t *bit_writer_create(uint8_t *bytes, size_t len) {
|
|
bit_writer_t *w = calloc(1, sizeof(bit_writer_t));
|
|
|
|
if (bytes) {
|
|
bit_writer_reconfigure(w, bytes, len);
|
|
}
|
|
|
|
return w;
|
|
}
|
|
|
|
void bit_writer_reconfigure(bit_writer_t *w, uint8_t *bytes, size_t len) {
|
|
w->bytes = bytes;
|
|
w->len = len;
|
|
|
|
w->current_byte = 0;
|
|
w->current_byte_len = 0;
|
|
w->byte_index = 0;
|
|
}
|
|
|
|
void bit_writer_destroy(bit_writer_t *w) {
|
|
free(w);
|
|
}
|
|
|
|
void bit_writer_write(bit_writer_t *w, uint8_t val, unsigned int n) {
|
|
for (size_t j = 0; j < n; j++) {
|
|
bit_writer_write_1(w, val);
|
|
val >>= 1;
|
|
}
|
|
}
|
|
|
|
void bit_writer_write_1(bit_writer_t *w, uint8_t val) {
|
|
w->current_byte |= val & 1;
|
|
w->current_byte_len++;
|
|
|
|
if (w->current_byte_len == 8) {
|
|
// 8 bits in a byte -- move to the next byte
|
|
w->bytes[w->byte_index] = w->current_byte;
|
|
w->byte_index++;
|
|
w->current_byte_len = 0;
|
|
w->current_byte = 0;
|
|
} else {
|
|
w->current_byte <<= 1;
|
|
}
|
|
}
|
|
|
|
void bit_writer_write_bitlist(bit_writer_t *w, uint8_t *l, size_t len) {
|
|
// first close the current byte
|
|
// we might have been given too few elements to do that. be careful.
|
|
size_t close_len = 8 - w->current_byte_len;
|
|
close_len = (close_len < len) ? close_len : len;
|
|
|
|
uint16_t b = w->current_byte;
|
|
|
|
for (ptrdiff_t i = 0; i < close_len; i++) {
|
|
b |= l[i];
|
|
b <<= 1;
|
|
}
|
|
|
|
|
|
l += close_len;
|
|
len -= close_len;
|
|
|
|
uint8_t *bytes = w->bytes;
|
|
size_t byte_index = w->byte_index;
|
|
|
|
if (w->current_byte_len + close_len == 8) {
|
|
b >>= 1;
|
|
bytes[byte_index] = b;
|
|
byte_index++;
|
|
} else {
|
|
w->current_byte = b;
|
|
w->current_byte_len += close_len;
|
|
return;
|
|
}
|
|
|
|
size_t full_bytes = len/8;
|
|
|
|
for (size_t i = 0; i < full_bytes; i++) {
|
|
bytes[byte_index] = l[0] << 7 | l[1] << 6 | l[2] << 5 |
|
|
l[3] << 4 | l[4] << 3 | l[5] << 2 |
|
|
l[6] << 1 | l[7];
|
|
byte_index += 1;
|
|
l += 8;
|
|
}
|
|
|
|
len -= 8*full_bytes;
|
|
|
|
b = 0;
|
|
for (ptrdiff_t i = 0; i < len; i++) {
|
|
b |= l[i];
|
|
b <<= 1;
|
|
}
|
|
|
|
w->current_byte = b;
|
|
w->byte_index = byte_index;
|
|
w->current_byte_len = len;
|
|
}
|
|
|
|
void bit_writer_write_bitlist_reversed(bit_writer_t *w, uint8_t *l, size_t len) {
|
|
l = l + len - 1;
|
|
|
|
uint8_t *bytes = w->bytes;
|
|
size_t byte_index = w->byte_index;
|
|
uint16_t b;
|
|
|
|
if (w->current_byte_len != 0) {
|
|
size_t close_len = 8 - w->current_byte_len;
|
|
close_len = (close_len < len) ? close_len : len;
|
|
|
|
b = w->current_byte;
|
|
|
|
for (ptrdiff_t i = 0; i < close_len; i++) {
|
|
b |= *l;
|
|
b <<= 1;
|
|
l--;
|
|
}
|
|
|
|
len -= close_len;
|
|
|
|
if (w->current_byte_len + close_len == 8) {
|
|
b >>= 1;
|
|
bytes[byte_index] = b;
|
|
byte_index++;
|
|
} else {
|
|
w->current_byte = b;
|
|
w->current_byte_len += close_len;
|
|
return;
|
|
}
|
|
}
|
|
|
|
size_t full_bytes = len/8;
|
|
|
|
for (size_t i = 0; i < full_bytes; i++) {
|
|
bytes[byte_index] = l[0] << 7 | l[-1] << 6 | l[-2] << 5 |
|
|
l[-3] << 4 | l[-4] << 3 | l[-5] << 2 |
|
|
l[-6] << 1 | l[-7];
|
|
byte_index += 1;
|
|
l -= 8;
|
|
}
|
|
|
|
len -= 8*full_bytes;
|
|
|
|
b = 0;
|
|
for (ptrdiff_t i = 0; i < len; i++) {
|
|
b |= *l;
|
|
b <<= 1;
|
|
l--;
|
|
}
|
|
|
|
w->current_byte = (uint8_t)b;
|
|
w->byte_index = byte_index;
|
|
w->current_byte_len = len;
|
|
}
|
|
|
|
void bit_writer_flush_byte(bit_writer_t *w) {
|
|
if (w->current_byte_len != 0) {
|
|
w->current_byte <<= (8 - w->current_byte_len);
|
|
w->bytes[w->byte_index] = w->current_byte;
|
|
w->byte_index++;
|
|
w->current_byte_len = 0;
|
|
}
|
|
}
|
|
|
|
size_t bit_writer_length(bit_writer_t *w) {
|
|
return w->byte_index;
|
|
}
|
|
|
|
uint8_t reverse_byte(uint8_t b) {
|
|
return (b & 0x80) >> 7 | (b & 0x40) >> 5 | (b & 0x20) >> 3 |
|
|
(b & 0x10) >> 1 | (b & 0x08) << 1 | (b & 0x04) << 3 |
|
|
(b & 0x02) << 5 | (b & 0x01) << 7;
|
|
}
|
|
|
|
static uint8_t reverse_table[256];
|
|
|
|
void create_reverse_table() {
|
|
for (uint16_t i = 0; i < 256; i++) {
|
|
reverse_table[i] = reverse_byte(i);
|
|
}
|
|
}
|
|
|
|
bit_reader_t *bit_reader_create(const uint8_t *bytes, size_t len) {
|
|
bit_reader_t *r = calloc(1, sizeof(bit_reader_t));
|
|
|
|
static bool reverse_table_created = false;
|
|
|
|
if (!reverse_table_created) {
|
|
create_reverse_table();
|
|
reverse_table_created = true;
|
|
}
|
|
|
|
if (bytes) {
|
|
bit_reader_reconfigure(r, bytes, len);
|
|
}
|
|
|
|
return r;
|
|
}
|
|
|
|
void bit_reader_reconfigure(bit_reader_t *r, const uint8_t *bytes, size_t len) {
|
|
r->bytes = bytes;
|
|
r->len = len;
|
|
|
|
r->current_byte_len = 8;
|
|
r->current_byte = bytes[0];
|
|
r->byte_index = 0;
|
|
}
|
|
|
|
void bit_reader_destroy(bit_reader_t *r) {
|
|
free(r);
|
|
}
|
|
|
|
uint8_t bit_reader_read(bit_reader_t *r, unsigned int n) {
|
|
unsigned int read = 0;
|
|
unsigned int n_copy = n;
|
|
|
|
if (r->current_byte_len < n) {
|
|
read = r->current_byte & ((1 << r->current_byte_len) - 1);
|
|
r->byte_index++;
|
|
r->current_byte = r->bytes[r->byte_index];
|
|
n -= r->current_byte_len;
|
|
r->current_byte_len = 8;
|
|
read <<= n;
|
|
}
|
|
|
|
uint8_t copy_mask = (1 << n) - 1;
|
|
copy_mask <<= (r->current_byte_len - n);
|
|
read |= (r->current_byte & copy_mask) >> (r->current_byte_len - n);
|
|
r->current_byte_len -= n;
|
|
return reverse_table[read] >> (8 - n_copy);
|
|
}
|