Jan Hrach has uploaded this change for review. (
https://gerrit.osmocom.org/10271
Change subject: simplify and speed up the burst synchronizer
......................................................................
simplify and speed up the burst synchronizer
Rewrite the burst synchronizer so we simply jump to the next training sequence.
I believe the state machine is not needed, the only reason for it - speeding
up search for the next frame - has been fixed in ca6a3bc.
Simplifying the synchronizer allows it to be easily extended to support
uplink and direct modes.
Additionally, we process the entire buffer at once (the previous version used
64-byte chunks), so the overhead is much smaller (up to 20 times on sparse
channels).
Change-Id: I74a13ced4c11b6d98afa7916c1f4109875c20101
---
M src/phy/tetra_burst_sync.c
M src/phy/tetra_burst_sync.h
M src/tetra-rx.c
M src/tetra_common.h
4 files changed, 65 insertions(+), 94 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/osmo-tetra refs/changes/71/10271/1
diff --git a/src/phy/tetra_burst_sync.c b/src/phy/tetra_burst_sync.c
index ae210dc..f3b759f 100644
--- a/src/phy/tetra_burst_sync.c
+++ b/src/phy/tetra_burst_sync.c
@@ -21,6 +21,7 @@
#include <stdint.h>
#include <stdio.h>
#include <string.h>
+#include <assert.h>
#include <osmocom/core/utils.h>
@@ -35,7 +36,7 @@
void tetra_burst_rx_cb(const uint8_t *burst, unsigned int len, enum
tetra_train_seq type, void *priv);
-static void make_bitbuf_space(struct tetra_rx_state *trs, unsigned int len)
+static unsigned int make_bitbuf_space(struct tetra_rx_state *trs, unsigned int
len)
{
unsigned int bitbuf_space = sizeof(trs->bitbuf) - trs->bits_in_buf;
@@ -48,9 +49,20 @@
trs->bitbuf_start_bitnum += delta;
bitbuf_space = sizeof(trs->bitbuf) - trs->bits_in_buf;
}
+ return bitbuf_space;
}
-/* input a raw bitstream into the tetra burst synchronizaer */
+static unsigned int conserve_bits(struct tetra_rx_state *trs, unsigned int
howmany)
+{
+ assert(howmany < sizeof(trs->bitbuf));
+ return make_bitbuf_space(trs, sizeof(trs->bitbuf) - howmany);
+}
+
+/* input a raw bitstream into the tetra burst synchronizer
+ * returns the number which in absolute value is the number of bits
+ * we can safely consume the next time
+ * if the result is negative, we are done with processing
+ */
int tetra_burst_sync_in(struct tetra_rx_state *trs, uint8_t *bits, unsigned
int len)
{
int rc;
@@ -63,92 +75,35 @@
memcpy(trs->bitbuf + trs->bits_in_buf, bits, len);
trs->bits_in_buf += len;
- switch (trs->state) {
- case RX_S_UNLOCKED:
- if (trs->bits_in_buf < TETRA_BITS_PER_TS*2) {
- /* wait for more bits to arrive */
- DEBUGP("-> waiting for more bits to arrive\n");
- return len;
- }
- DEBUGP("-> trying to find training sequence between bit %u and
%u\n",
- trs->bitbuf_start_bitnum, trs->bits_in_buf);
- rc = tetra_find_train_seq(trs->bitbuf, trs->bits_in_buf,
- (1 << TETRA_TRAIN_SYNC),
&train_seq_offs);
- if (rc < 0)
- return rc;
- printf("found SYNC training sequence in bit #%u\n",
train_seq_offs);
- trs->state = RX_S_KNOW_FSTART;
- trs->next_frame_start_bitnum = trs->bitbuf_start_bitnum +
train_seq_offs + 296;
-#if 0
- if (train_seq_offs < 214) {
- /* not enough leading bits for start of burst */
- /* we just drop everything that we received so far */
- trs->bitbuf_start_bitnum += trs->bits_in_buf;
- trs->bits_in_buf = 0;
- }
-#endif
+ rc = tetra_find_train_seq(trs->bitbuf+214, trs->bits_in_buf,
+ (1 << TETRA_TRAIN_NORM_1)|
+ (1 << TETRA_TRAIN_NORM_2)|
+ (1 << TETRA_TRAIN_SYNC), &train_seq_offs);
+ train_seq_offs += 214;
+
+ if ((rc < 0) || (train_seq_offs + TETRA_BITS_PER_TS > trs->bits_in_buf))
+ return -conserve_bits(trs, 2*TETRA_BITS_PER_TS);
+
+ tetra_tdma_time_add_tn(&t_phy_state.time, 1);
+ printf("\nBURST @ %u", trs->bitbuf_start_bitnum+train_seq_offs);
+ DEBUGP(": %s", osmo_ubit_dump(trs->bitbuf, TETRA_BITS_PER_TS));
+ printf("\n");
+
+ switch (rc) {
+ case TETRA_TRAIN_SYNC:
+ if (train_seq_offs >= 214)
+ tetra_burst_rx_cb(trs->bitbuf+train_seq_offs-214,
TETRA_BITS_PER_TS, rc, trs->burst_cb_priv);
break;
- case RX_S_KNOW_FSTART:
- /* we are locked, i.e. already know when the next frame should
start */
- if (trs->bitbuf_start_bitnum + trs->bits_in_buf <
trs->next_frame_start_bitnum)
- return 0;
- else {
- /* shift start of frame to start of bitbuf */
- int offset = trs->next_frame_start_bitnum -
trs->bitbuf_start_bitnum;
- int bits_remaining = trs->bits_in_buf - offset;
-
- memmove(trs->bitbuf, trs->bitbuf+offset,
bits_remaining);
- trs->bits_in_buf = bits_remaining;
- trs->bitbuf_start_bitnum += offset;
-
- trs->next_frame_start_bitnum += TETRA_BITS_PER_TS;
- trs->state = RX_S_LOCKED;
- }
- case RX_S_LOCKED:
- if (trs->bits_in_buf < TETRA_BITS_PER_TS) {
- /* not sufficient data for the full frame yet */
- return len;
- } else {
- /* we have successfully received (at least) one frame */
- tetra_tdma_time_add_tn(&t_phy_state.time, 1);
- printf("\nBURST");
- DEBUGP(": %s", osmo_ubit_dump(trs->bitbuf,
TETRA_BITS_PER_TS));
- printf("\n");
- rc = tetra_find_train_seq(trs->bitbuf, trs->bits_in_buf,
- (1 << TETRA_TRAIN_NORM_1)|
- (1 << TETRA_TRAIN_NORM_2)|
- (1 << TETRA_TRAIN_SYNC),
&train_seq_offs);
- switch (rc) {
- case TETRA_TRAIN_SYNC:
- if (train_seq_offs == 214)
- tetra_burst_rx_cb(trs->bitbuf,
TETRA_BITS_PER_TS, rc, trs->burst_cb_priv);
- else {
- fprintf(stderr, "#### SYNC burst at
offset %u?!?\n", train_seq_offs);
- trs->state = RX_S_UNLOCKED;
- }
- break;
- case TETRA_TRAIN_NORM_1:
- case TETRA_TRAIN_NORM_2:
- case TETRA_TRAIN_NORM_3:
- if (train_seq_offs == 244)
- tetra_burst_rx_cb(trs->bitbuf,
TETRA_BITS_PER_TS, rc, trs->burst_cb_priv);
- else
- fprintf(stderr, "#### SYNC burst at
offset %u?!?\n", train_seq_offs);
- break;
- default:
- fprintf(stderr, "#### could not find successive
burst training sequence\n");
- trs->state = RX_S_UNLOCKED;
- break;
- }
-
- /* move remainder to start of buffer */
- trs->bits_in_buf -= TETRA_BITS_PER_TS;
- memmove(trs->bitbuf, trs->bitbuf+TETRA_BITS_PER_TS,
trs->bits_in_buf);
- trs->bitbuf_start_bitnum += TETRA_BITS_PER_TS;
- trs->next_frame_start_bitnum += TETRA_BITS_PER_TS;
- }
+ case TETRA_TRAIN_NORM_1:
+ case TETRA_TRAIN_NORM_2:
+ case TETRA_TRAIN_NORM_3:
+ if (train_seq_offs >= 244)
+ tetra_burst_rx_cb(trs->bitbuf+train_seq_offs-244,
TETRA_BITS_PER_TS, rc, trs->burst_cb_priv);
break;
-
+ default:
+ fprintf(stderr, "#### unsupported burst training sequence\n");
+ break;
}
- return len;
+ return train_seq_offs+1;
+
}
diff --git a/src/phy/tetra_burst_sync.h b/src/phy/tetra_burst_sync.h
index 7862461..4ec8b53 100644
--- a/src/phy/tetra_burst_sync.h
+++ b/src/phy/tetra_burst_sync.h
@@ -3,6 +3,8 @@
#include <stdint.h>
+#define BUFSIZE 4096
+
enum rx_state {
RX_S_UNLOCKED, /* we're completely unlocked */
RX_S_KNOW_FSTART, /* we know the next frame start */
@@ -12,7 +14,7 @@
struct tetra_rx_state {
enum rx_state state;
unsigned int bits_in_buf; /* how many bits are currently
in bitbuf */
- uint8_t bitbuf[4096];
+ uint8_t bitbuf[BUFSIZE];
unsigned int bitbuf_start_bitnum; /* bit number at first element
in bitbuf */
unsigned int next_frame_start_bitnum; /* frame start expected at this
bitnum */
diff --git a/src/tetra-rx.c b/src/tetra-rx.c
index 8498f8c..78bdfea 100644
--- a/src/tetra-rx.c
+++ b/src/tetra-rx.c
@@ -95,19 +95,29 @@
if (pcap_file_path)
tetra_gsmtap_init_file(pcap_file_path);
- while (1) {
- uint8_t buf[64];
- int len;
+ int to_consume = BUFSIZE;
+ uint8_t buf[BUFSIZE];
- len = read(fd, buf, sizeof(buf));
+ while (1) {
+ int len, rlen;
+
+ len = read(fd, buf, to_consume);
if (len < 0) {
perror("read");
exit(1);
- } else if (len == 0) {
+ }
+ rlen = len;
+ if (len == 0) {
+ memset(buf, 0, BUFSIZE);
+ rlen = to_consume;
+ }
+ int rc = tetra_burst_sync_in(trs, buf, rlen);
+
+ if (len == 0 && rc <= 0) {
printf("EOF");
break;
}
- tetra_burst_sync_in(trs, buf, len);
+ to_consume = MIN(abs(rc), BUFSIZE);
}
free(tms->dumpdir);
diff --git a/src/tetra_common.h b/src/tetra_common.h
index a270a26..c63e6ca 100644
--- a/src/tetra_common.h
+++ b/src/tetra_common.h
@@ -11,6 +11,10 @@
#define DEBUGP(x, args...) do { } while(0)
#endif
+#define MIN(a, b) (((a) < (b))?(a):(b))
+#define MAX(a, b) (((a) > (b))?(a):(b))
+#define CLAMP(x, lower, upper) (MIN(upper, MAX(x, lower)))
+
#define TETRA_SYM_PER_TS 255
#define TETRA_BITS_PER_TS (TETRA_SYM_PER_TS*2)
--
To view, visit https://gerrit.osmocom.org/10271
To unsubscribe, or for help writing mail filters, visit
https://gerrit.osmocom.org/settings
Gerrit-Project: osmo-tetra
Gerrit-Branch: master
Gerrit-MessageType: newchange
Gerrit-Change-Id: I74a13ced4c11b6d98afa7916c1f4109875c20101
Gerrit-Change-Number: 10271
Gerrit-PatchSet: 1
Gerrit-Owner: Jan Hrach <[email protected]>