Merge pull request #1 from luckyhacky/master

I will continue development on brmlabs osmo-tetra (and merge this into brmlabs repository)
This commit is contained in:
Jiří Pinkava 2014-11-17 14:59:05 +01:00
commit f7479db0d2
15 changed files with 206 additions and 48 deletions

View file

@ -306,8 +306,11 @@ int build_sb()
int main(int argc, char **argv)
{
int err, i;
int i;
#if 0
int err;
uint16_t out;
#endif
uint32_t ret;
/* first: run some subsystem tests */

View file

@ -27,7 +27,7 @@
differential PI/4 CQPSK modulation and demodulation.
"""
from gnuradio import gr, gru, blocks, analog, filter
from gnuradio import gr, gru, blocks, analog, filter, digital
from gnuradio.filter import firdes
from math import pi, sqrt
#import psk

View file

@ -40,6 +40,7 @@ class top_block(grc_wxgui.top_block_gui):
self.ifreq = options.frequency
self.rfgain = options.gain
self.offset = options.frequency_offset
self.src = osmosdr.source(options.args)
self.src.set_center_freq(self.ifreq)
@ -173,8 +174,8 @@ class top_block(grc_wxgui.top_block_gui):
if abs(x / (sample_rate / 2)) > 0.9:
set_ifreq(self.ifreq + x / 2)
else:
sys.stderr.write("coarse tuned to: %d Hz\n" % x)
self.offset = -x
sys.stderr.write("coarse tuned to: %d Hz => %d Hz\n" % (self.offset, (self.ifreq + self.offset)))
self.tuner.set_center_freq(self.offset)
self.scope = fftsink2.fft_sink_c(self.Main.GetPage(0).GetWin(),
@ -195,7 +196,7 @@ class top_block(grc_wxgui.top_block_gui):
def fftsink2_callback2(x, y):
self.offset = self.offset - (x / 10)
sys.stderr.write("fine tuned to: %d Hz\n" % self.offset)
sys.stderr.write("fine tuned to: %d Hz => %d Hz\n" % (self.offset, (self.ifreq + self.offset)))
self.tuner.set_center_freq(self.offset)
self.scope2 = fftsink2.fft_sink_c(self.Main.GetPage(1).GetWin(),
@ -240,6 +241,8 @@ def get_options():
help="set receiver sample rate (default 1800000)")
parser.add_option("-f", "--frequency", type="eng_float", default=394.4e6,
help="set receiver center frequency")
parser.add_option("-F", "--frequency-offset", type="eng_float", default=0,
help="set receiver offset frequency")
parser.add_option("-g", "--gain", type="eng_float", default=None,
help="set receiver gain")

View file

@ -2,8 +2,9 @@
import sys
import math
from gnuradio import gr, gru, audio, eng_notation, blks2, optfir
from gnuradio import gr, gru, audio, eng_notation, filter, blocks
from gnuradio import uhd
from gnuradio.filter import firdes
from gnuradio.eng_option import eng_option
from optparse import OptionParser
@ -63,9 +64,9 @@ class my_top_block(gr.top_block):
sys.stderr.write('Failed to set center frequency\n')
raise SystemExit, 1
channel_taps = gr.firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.1, gr.firdes.WIN_HANN)
channel_taps = firdes.low_pass(1.0, sample_rate, options.low_pass, options.low_pass * 0.1, firdes.WIN_HANN)
FILTER = gr.freq_xlating_fir_filter_ccf(1, channel_taps, options.calibration, sample_rate)
FILTER = filter.freq_xlating_fir_filter_ccf(1, channel_taps, options.calibration, sample_rate)
sys.stderr.write("sample rate: %d\n" %(sample_rate))
@ -78,11 +79,11 @@ class my_top_block(gr.top_block):
log=options.log,
verbose=options.verbose)
OUT = gr.file_sink(gr.sizeof_float, options.output_file)
OUT = blocks.file_sink(gr.sizeof_float, options.output_file)
r = float(sample_rate) / float(new_sample_rate)
INTERPOLATOR = gr.fractional_interpolator_cc(0, r)
INTERPOLATOR = filter.fractional_interpolator_cc(0, r)
self.connect(self._u, FILTER, INTERPOLATOR, DEMOD, OUT)

View file

@ -31,6 +31,7 @@
#include <tetra_common.h>
#include <lower_mac/tetra_conv_enc.h>
#if 0
static char *dump_state(struct conv_enc_state *ces)
{
static char pbuf[1024];
@ -38,6 +39,7 @@ static char *dump_state(struct conv_enc_state *ces)
ces->delayed[1], ces->delayed[2], ces->delayed[3]);
return pbuf;
}
#endif
/* Mother code according to Section 8.2.3.1.1 */
static uint8_t conv_enc_in_bit(struct conv_enc_state *ces, uint8_t bit, uint8_t *out)

View file

@ -314,6 +314,10 @@ void tetra_burst_rx_cb(const uint8_t *burst, unsigned int len, enum tetra_train_
uint8_t ndbf_buf[2*NDB_BLK_BITS];
switch (type) {
case TETRA_TRAIN_EXT:
// TODO: currently not handled!
// FIXME
break;
case TETRA_TRAIN_SYNC:
/* Split SB1, SB2 and Broadcast Block */
/* send three parts of the burst via TP-SAP into lower MAC */
@ -321,6 +325,10 @@ void tetra_burst_rx_cb(const uint8_t *burst, unsigned int len, enum tetra_train_
tp_sap_udata_ind(TPSAP_T_BBK, burst+SB_BBK_OFFSET, SB_BBK_BITS, priv);
tp_sap_udata_ind(TPSAP_T_SB2, burst+SB_BLK2_OFFSET, SB_BLK2_BITS, priv);
break;
case TETRA_TRAIN_NORM_3:
// TODO: currently not handled!
// FIXME
break;
case TETRA_TRAIN_NORM_2:
/* re-combine the broadcast block */
memcpy(bbk_buf, burst+NDB_BBK1_OFFSET, NDB_BBK1_BITS);

View file

@ -34,23 +34,79 @@
#include <phy/tetra_burst_sync.h>
#include "tetra_gsmtap.h"
// size of IO buffers (number of elements)
#define BUF_SIZE 256
void *tetra_tall_ctx;
static int process_sym_fl(float fl)
{
int ret;
/* very simplistic scheme */
if (fl > 2)
ret = 3;
else if (fl > 0)
ret = 1;
else if (fl < -2)
ret = -3;
else
ret = -1;
return ret;
}
static void sym_int2bits(int sym, uint8_t *ret)
{
switch (sym) {
case -3:
ret[0] = 1;
ret[1] = 1;
break;
case 1:
ret[0] = 0;
ret[1] = 0;
break;
case 3:
ret[0] = 0;
ret[1] = 1;
break;
case -1:
ret[0] = 1;
ret[1] = 0;
break;
}
}
int main(int argc, char **argv)
{
int fd;
int opt;
int streaming = 0;
int opt_verbose = 0;
struct tetra_rx_state *trs;
struct tetra_mac_state *tms;
if (argc < 2) {
fprintf(stderr, "Usage: %s <file_with_1_byte_per_bit>\n", argv[0]);
exit(1);
while ((opt = getopt(argc, argv, "sv")) != -1) {
switch (opt) {
case 's':
streaming = 1;
break;
case 'v':
opt_verbose = 1;
break;
default:
exit(2);
}
}
fd = open(argv[1], O_RDONLY);
if (fd < 0) {
perror("open");
exit(2);
if (argc <= optind) {
fprintf(stderr, "Usage: %s -s [-v] <filestream>\n", argv[0]);
fprintf(stderr, "Usage: %s <file_with_1_byte_per_bit>\n", argv[0]);
exit(1);
}
tetra_gsmtap_init("localhost", 0);
@ -60,22 +116,55 @@ int main(int argc, char **argv)
trs = talloc_zero(tetra_tall_ctx, struct tetra_rx_state);
trs->burst_cb_priv = tms;
while (1) {
uint8_t buf[64];
int len;
len = read(fd, buf, sizeof(buf));
if (len < 0) {
perror("read");
exit(1);
} else if (len == 0) {
printf("EOF");
break;
}
tetra_burst_sync_in(trs, buf, len);
fd = open(argv[optind], O_RDONLY);
if (fd < 0) {
perror("open");
exit(2);
}
// use old mode which uses files with 1 byte per bit
if(streaming == 0) {
while (1) {
uint8_t buf[64];
int len;
len = read(fd, buf, sizeof(buf));
if (len < 0) {
perror("read");
exit(1);
} else if (len == 0) {
printf("EOF");
break;
}
tetra_burst_sync_in(trs, buf, len);
}
}
else { // new fast mode - we will decode the incoming file ourself
while (1) {
int rc;
float fl[BUF_SIZE];
uint8_t bits[2*BUF_SIZE];
rc = read(fd, fl, sizeof(*fl) * BUF_SIZE);
if (rc < 0) {
perror("read");
exit(1);
} else if (rc == 0) {
break;
}
rc /= sizeof(*fl);
int i;
for (i = 0; i < rc; ++i) {
int sym = process_sym_fl(fl[i]);
sym_int2bits(sym, bits + i*2);
if (opt_verbose) {
printf("%1u%1u", bits[2*i + 0], bits[2*i + 1]);
}
}
tetra_burst_sync_in(trs, bits, rc * 2);
}
}
talloc_free(trs);
talloc_free(tms);

View file

@ -28,6 +28,7 @@
#include <osmocom/core/bits.h>
#include "tetra_llc_pdu.h"
#include "tuntap.h"
static int tun_fd = -1;
@ -78,7 +79,7 @@ static int tllc_defrag_in(struct tllc_state *llcs,
return 0;
}
static int tllc_defrag_out(struct tllc_state *llcs,
static void tllc_defrag_out(struct tllc_state *llcs,
struct tetra_llc_pdu *lpp)
{
struct tllc_defrag_q_e *dqe;
@ -147,6 +148,18 @@ int rx_tm_sdu(struct msgb *msg, unsigned int len)
/* check if the fragment is complete and hand it off*/
tllc_defrag_out(&g_llcs, &lpp);
break;
case TLLC_PDUT_DEC_UNKNOWN:
// TODO: currently not handled!
// FIXME
break;
case TLLC_PDUT_DEC_ALX_ACK:
// TODO: currently not handled!
// FIXME
break;
case TLLC_PDUT_DEC_ALX_RNR:
// TODO: currently not handled!
// FIXME
break;
}
if (lpp.tl_sdu && lpp.ss == 0) {

View file

@ -39,28 +39,45 @@ static void decode_d_mle_sysinfo(struct tetra_mle_si_decoded *msid, const uint8_
msid->bs_service_details = bits_to_uint(cur, 12); cur += 12;
}
/* see 21.4.4.1 */
void macpdu_decode_sysinfo(struct tetra_si_decoded *sid, const uint8_t *si_bits)
{
const uint8_t *cur = si_bits + 4;
const uint8_t *cur = si_bits;
cur += 2; // skip Broadcast PDU header
cur += 2; // skip Sysinfo PDU header
sid->main_carrier = bits_to_uint(cur, 12); cur += 12;
sid->freq_band = bits_to_uint(cur, 4); cur += 4;
sid->freq_offset = bits_to_uint(cur, 2); cur += 2;
sid->duplex_spacing = bits_to_uint(cur, 3); cur += 3;
sid->main_carrier = bits_to_uint(cur, 12); cur += 12;
sid->freq_band = bits_to_uint(cur, 4); cur += 4;
sid->freq_offset = bits_to_uint(cur, 2); cur += 2;
sid->duplex_spacing = bits_to_uint(cur, 3); cur += 3;
sid->reverse_operation = *cur++;
sid->num_of_csch = bits_to_uint(cur, 2); cur +=2;
sid->ms_txpwr_max_cell = bits_to_uint(cur, 3); cur += 3;
sid->rxlev_access_min = bits_to_uint(cur, 4); cur += 4;
sid->access_parameter = bits_to_uint(cur, 4); cur += 4;
sid->radio_dl_timeout = bits_to_uint(cur, 4); cur += 4;
sid->cck_valid_no_hf = *cur++;
sid->num_of_csch = bits_to_uint(cur, 2); cur += 2;
sid->ms_txpwr_max_cell = bits_to_uint(cur, 3); cur += 3;
sid->rxlev_access_min = bits_to_uint(cur, 4); cur += 4;
sid->access_parameter = bits_to_uint(cur, 4); cur += 4;
sid->radio_dl_timeout = bits_to_uint(cur, 4); cur += 4;
sid->cck_valid_no_hf = *cur++;
if (sid->cck_valid_no_hf)
sid->cck_id = bits_to_uint(cur, 16);
else
sid->hyperframe_number = bits_to_uint(cur, 16);
cur += 16;
/* FIXME: more */
decode_d_mle_sysinfo(&sid->mle_si, si_bits + 124-42);
sid->option_field = bits_to_uint(cur, 2); cur += 2;
switch(sid->option_field)
{
case TETRA_MAC_OPT_FIELD_EVEN_MULTIFRAME: // Even multiframe definition for TS mode
case TETRA_MAC_OPT_FIELD_ODD_MULTIFRAME: // Odd multiframe definition for TS mode
sid->frame_bitmap = bits_to_uint(cur, 20); cur += 20;
break;
case TETRA_MAC_OPT_FIELD_ACCESS_CODE: // Default definition for access code A
sid->access_code = bits_to_uint(cur, 20); cur += 20;
break;
case TETRA_MAC_OPT_FIELD_EXT_SERVICES: // Extended services broadcast
sid->ext_service = bits_to_uint(cur, 20); cur += 20;
break;
}
decode_d_mle_sysinfo(&sid->mle_si, si_bits + 124-42); // could be also cur due to previous fixes
}
static const uint8_t addr_len_by_type[] = {

View file

@ -36,6 +36,13 @@ enum tetra_bs_serv_details {
BS_SERVDET_ADV_LINK = (1 << 0),
};
enum tetra_mac_optional_field_flags {
TETRA_MAC_OPT_FIELD_EVEN_MULTIFRAME = 0,
TETRA_MAC_OPT_FIELD_ODD_MULTIFRAME = 1,
TETRA_MAC_OPT_FIELD_ACCESS_CODE = 2,
TETRA_MAC_OPT_FIELD_EXT_SERVICES = 3
};
const char *tetra_get_bs_serv_det_name(uint32_t pdu_type);
struct tetra_mle_si_decoded {
@ -60,6 +67,12 @@ struct tetra_si_decoded {
uint16_t cck_id;
uint16_t hyperframe_number;
};
uint8_t option_field;
union {
uint32_t frame_bitmap;
uint32_t access_code;
uint32_t ext_service;
};
struct tetra_mle_si_decoded mle_si;
};

View file

@ -9,7 +9,7 @@
enum tetra_saps {
TETRA_SAP_TP, /* between PHY and lower MAC */
TETRA_SAP_TMV, /* beetween lower and upper MAC */
TETRA_SAP_TMV, /* between lower and upper MAC */
TETRA_SAP_TMA,
TETRA_SAP_TMB,
TETRA_SAP_TMD,

View file

@ -95,6 +95,5 @@ char *tetra_tdma_time_dump(const struct tetra_tdma_time *tm)
uint32_t tetra_tdma_time2fn(struct tetra_tdma_time *tm)
{
/* FIXME: add hyperframe number !! */
return (tm->mn *18) + tm->fn;
return (((tm->hn * 60) + tm->mn) * 18) + tm->fn;
}

View file

@ -4,6 +4,7 @@
#include <stdint.h>
struct tetra_tdma_time {
uint16_t hn; /* hyperframe number (1 ... 65535) */
uint32_t sn; /* symbol number (1 ... 255) */
uint32_t tn; /* timeslot number (1 .. 4) */
uint32_t fn; /* frame number (1 .. 18) */

View file

@ -49,6 +49,7 @@ static void rx_bcast(struct tetra_tmvsap_prim *tmvp, struct tetra_mac_state *tms
memset(&sid, 0, sizeof(sid));
macpdu_decode_sysinfo(&sid, msg->l1h);
tmvp->u.unitdata.tdma_time.hn = sid.hyperframe_number;
dl_freq = tetra_dl_carrier_hz(sid.freq_band,
sid.main_carrier,

8
src/tuntap.h Normal file
View file

@ -0,0 +1,8 @@
#ifndef TUNTAP_H
#define TUNTAP_H
/* Allocate a tun interface */
int tun_alloc(char *dev);
#endif /* TUNTAP_H */