Bug #1897 ยป tetra.patch
src/phy/tetra_burst.c | ||
---|---|---|
23 | 23 |
#include <stdint.h> |
24 | 24 |
#include <string.h> |
25 | 25 |
#include <stdio.h> |
26 |
#include <stdbool.h> |
|
26 | 27 | |
27 | 28 |
#include <phy/tetra_burst.h> |
28 | 29 | |
... | ... | |
266 | 267 |
return cur - buf; |
267 | 268 |
} |
268 | 269 | |
270 |
/* |
|
271 |
* Initialize a fast filter for searching for training sequences. |
|
272 |
* After this function is called, each element of @tsq_all contains the first |
|
273 |
* @FILTER_LOOKAHEAD_LEN bits of a given training sequence. |
|
274 |
* Then, we can search for a given sequence using a single compare. |
|
275 |
*/ |
|
276 |
uint32_t tsq_all[5]; |
|
277 |
#define FILTER_LOOKAHEAD_LEN 16 |
|
278 |
#define FILTER_LOOKAHEAD_MASK 0xFFFF |
|
279 |
void tetra_init_train_seq_filter() { |
|
280 |
for(int i = 0; i<FILTER_LOOKAHEAD_LEN; i++) { |
|
281 |
tsq_all[0] = (tsq_all[0] << 1) | y_bits[i]; |
|
282 |
tsq_all[1] = (tsq_all[1] << 1) | n_bits[i]; |
|
283 |
tsq_all[2] = (tsq_all[2] << 1) | p_bits[i]; |
|
284 |
tsq_all[3] = (tsq_all[3] << 1) | q_bits[i]; |
|
285 |
tsq_all[4] = (tsq_all[4] << 1) | x_bits[i]; |
|
286 |
} |
|
287 |
for(int i = 0; i < 5; i++) { |
|
288 |
tsq_all[i] &= FILTER_LOOKAHEAD_MASK; |
|
289 |
} |
|
290 |
} |
|
291 | ||
269 | 292 |
int tetra_find_train_seq(const uint8_t *in, unsigned int end_of_in, |
270 | 293 |
uint32_t mask_of_train_seq, unsigned int *offset) |
271 | 294 |
{ |
272 | 295 |
const uint8_t *cur; |
273 | 296 | |
297 |
uint32_t filter = 0; |
|
298 | ||
299 |
for (int i = 0; i<FILTER_LOOKAHEAD_LEN-2; i++) { |
|
300 |
filter = (filter << 1) | in[i]; |
|
301 |
} |
|
302 | ||
274 | 303 |
for (cur = in; cur < in + end_of_in; cur++) { |
304 |
/* |
|
305 |
* We are shifting the incoming bitstream into @filter. |
|
306 |
* Then, we compare the filter for the beginning of all the training sequence. |
|
307 |
* When this simple comparison matches, we use a full-blown memcmp for the |
|
308 |
* whole sequence. |
|
309 |
*/ |
|
310 |
filter = ((filter << 1) | cur[FILTER_LOOKAHEAD_LEN-1]) & FILTER_LOOKAHEAD_MASK; |
|
311 |
bool match = false; |
|
312 |
for(int i = 0; i<5; i++) { |
|
313 |
if(filter == tsq_all[i]) { |
|
314 |
match = true; |
|
315 |
} |
|
316 |
} |
|
317 |
if(!match) { |
|
318 |
continue; |
|
319 |
} |
|
320 | ||
275 | 321 |
int remain_len = (in + end_of_in) - cur; |
276 | 322 | |
277 | 323 |
if (mask_of_train_seq & (1 << TETRA_TRAIN_SYNC) && |
src/phy/tetra_burst.h | ||
---|---|---|
31 | 31 |
/* find a TETRA training sequence in the burst buffer indicated */ |
32 | 32 |
int tetra_find_train_seq(const uint8_t *in, unsigned int end_of_in, |
33 | 33 |
uint32_t mask_of_train_seq, unsigned int *offset); |
34 |
void tetra_init_train_seq_filter(); |
|
34 | 35 | |
35 | 36 |
#endif /* TETRA_BURST_H */ |
src/phy/tetra_burst_sync.c | ||
---|---|---|
35 | 35 | |
36 | 36 |
void tetra_burst_rx_cb(const uint8_t *burst, unsigned int len, enum tetra_train_seq type, void *priv); |
37 | 37 | |
38 |
static void make_bitbuf_space(struct tetra_rx_state *trs, unsigned int len) |
|
39 |
{ |
|
40 |
unsigned int bitbuf_space = sizeof(trs->bitbuf) - trs->bits_in_buf; |
|
41 | ||
42 |
if (bitbuf_space < len) { |
|
43 |
unsigned int delta = len - bitbuf_space; |
|
44 | ||
45 |
DEBUGP("bitbuf left: %u, shrinking by %u\n", bitbuf_space, delta); |
|
46 |
memmove(trs->bitbuf, trs->bitbuf + delta, trs->bits_in_buf - delta); |
|
47 |
trs->bits_in_buf -= delta; |
|
48 |
trs->bitbuf_start_bitnum += delta; |
|
49 |
bitbuf_space = sizeof(trs->bitbuf) - trs->bits_in_buf; |
|
50 |
} |
|
51 |
} |
|
52 | ||
53 |
/* input a raw bitstream into the tetra burst synchronizaer */ |
|
54 |
int tetra_burst_sync_in(struct tetra_rx_state *trs, uint8_t *bits, unsigned int len) |
|
38 |
/* input a raw bitstream file into the tetra burst synchronizaer */ |
|
39 |
int tetra_burst_sync_in(struct tetra_rx_state *trs, FILE *infile) |
|
55 | 40 |
{ |
56 | 41 |
int rc; |
57 | 42 |
unsigned int train_seq_offs; |
43 |
int len; |
|
44 |
int bits_free = sizeof(trs->bitbuf) - trs->bits_in_buf; |
|
58 | 45 | |
59 |
DEBUGP("burst_sync_in: %u bits, state %u\n", len, trs->state); |
|
46 |
len = fread(trs->bitbuf + trs->bits_in_buf, 1, bits_free, infile); |
|
47 | ||
48 |
if (len < 0) { |
|
49 |
perror("read"); |
|
50 |
exit(1); |
|
51 |
} else if (feof(infile) && trs->bits_in_buf < TETRA_BITS_PER_TS) { |
|
52 |
printf("EOF"); |
|
53 |
return -1; |
|
54 |
} |
|
60 | 55 | |
61 |
/* First: append the data to the bitbuf */ |
|
62 |
make_bitbuf_space(trs, len); |
|
63 |
memcpy(trs->bitbuf + trs->bits_in_buf, bits, len); |
|
64 | 56 |
trs->bits_in_buf += len; |
57 |
DEBUGP("burst_sync_in: %u bits, state %u\n", len, trs->state); |
|
65 | 58 | |
66 | 59 |
switch (trs->state) { |
67 | 60 |
case RX_S_UNLOCKED: |
68 | 61 |
if (trs->bits_in_buf < TETRA_BITS_PER_TS*2) { |
69 | 62 |
/* wait for more bits to arrive */ |
70 | 63 |
DEBUGP("-> waiting for more bits to arrive\n"); |
71 |
return len;
|
|
64 |
return trs->bits_in_buf;
|
|
72 | 65 |
} |
73 | 66 |
DEBUGP("-> trying to find training sequence between bit %u and %u\n", |
74 | 67 |
trs->bitbuf_start_bitnum, trs->bits_in_buf); |
75 | 68 |
rc = tetra_find_train_seq(trs->bitbuf, trs->bits_in_buf, |
76 | 69 |
(1 << TETRA_TRAIN_SYNC), &train_seq_offs); |
77 |
if (rc < 0) |
|
70 |
if (rc < 0) { |
|
71 |
memmove(trs->bitbuf, |
|
72 |
trs->bitbuf + trs->bits_in_buf - TETRA_BITS_PER_TS*2, |
|
73 |
TETRA_BITS_PER_TS*2); |
|
74 |
trs->bits_in_buf = TETRA_BITS_PER_TS*2; |
|
78 | 75 |
return rc; |
76 |
} |
|
79 | 77 |
printf("found SYNC training sequence in bit #%u\n", train_seq_offs); |
80 | 78 |
trs->state = RX_S_KNOW_FSTART; |
81 | 79 |
trs->next_frame_start_bitnum = trs->bitbuf_start_bitnum + train_seq_offs + 296; |
... | ... | |
91 | 89 |
case RX_S_KNOW_FSTART: |
92 | 90 |
/* we are locked, i.e. already know when the next frame should start */ |
93 | 91 |
if (trs->bitbuf_start_bitnum + trs->bits_in_buf < trs->next_frame_start_bitnum) |
94 |
return 0;
|
|
92 |
return trs->bits_in_buf;
|
|
95 | 93 |
else { |
96 | 94 |
/* shift start of frame to start of bitbuf */ |
97 | 95 |
int offset = trs->next_frame_start_bitnum - trs->bitbuf_start_bitnum; |
... | ... | |
107 | 105 |
case RX_S_LOCKED: |
108 | 106 |
if (trs->bits_in_buf < TETRA_BITS_PER_TS) { |
109 | 107 |
/* not sufficient data for the full frame yet */ |
110 |
return len;
|
|
108 |
return trs->bits_in_buf;
|
|
111 | 109 |
} else { |
112 | 110 |
/* we have successfully received (at least) one frame */ |
113 | 111 |
tetra_tdma_time_add_tn(&t_phy_state.time, 1); |
... | ... | |
150 | 148 |
break; |
151 | 149 | |
152 | 150 |
} |
153 |
return len;
|
|
151 |
return trs->bits_in_buf;
|
|
154 | 152 |
} |
src/phy/tetra_burst_sync.h | ||
---|---|---|
21 | 21 | |
22 | 22 | |
23 | 23 |
/* input a raw bitstream into the tetra burst synchronizaer */ |
24 |
int tetra_burst_sync_in(struct tetra_rx_state *trs, uint8_t *bits, unsigned int len);
|
|
24 |
int tetra_burst_sync_in(struct tetra_rx_state *trs, FILE *infile);
|
|
25 | 25 | |
26 | 26 |
#endif /* TETRA_BURST_SYNC_H */ |
src/tetra-rx.c | ||
---|---|---|
38 | 38 | |
39 | 39 |
int main(int argc, char **argv) |
40 | 40 |
{ |
41 |
int fd;
|
|
41 |
FILE *infile;
|
|
42 | 42 |
struct tetra_rx_state *trs; |
43 | 43 |
struct tetra_mac_state *tms; |
44 | 44 | |
... | ... | |
47 | 47 |
exit(1); |
48 | 48 |
} |
49 | 49 | |
50 |
fd = open(argv[1], O_RDONLY);
|
|
51 |
if (fd < 0) {
|
|
52 |
perror("open"); |
|
50 |
infile = fopen(argv[1], "r");
|
|
51 |
if (infile < 0) {
|
|
52 |
perror("fopen");
|
|
53 | 53 |
exit(2); |
54 | 54 |
} |
55 | 55 | |
... | ... | |
61 | 61 |
trs = talloc_zero(tetra_tall_ctx, struct tetra_rx_state); |
62 | 62 |
trs->burst_cb_priv = tms; |
63 | 63 | |
64 |
while (1) { |
|
65 |
uint8_t buf[64]; |
|
66 |
int len; |
|
67 | ||
68 |
len = read(fd, buf, sizeof(buf)); |
|
69 |
if (len < 0) { |
|
70 |
perror("read"); |
|
71 |
exit(1); |
|
72 |
} else if (len == 0) { |
|
73 |
printf("EOF"); |
|
74 |
break; |
|
75 |
} |
|
76 |
tetra_burst_sync_in(trs, buf, len); |
|
64 |
tetra_init_train_seq_filter(); |
|
65 | ||
66 |
int rc; |
|
67 |
while (!(feof(infile) && rc <= 0)) { |
|
68 |
rc = tetra_burst_sync_in(trs, infile); |
|
77 | 69 |
} |
70 |
fclose(infile); |
|
78 | 71 | |
79 | 72 |
talloc_free(trs); |
80 | 73 |
talloc_free(tms); |