diff options
-rw-r--r-- | grc/trx_interface/gsm_trx.xml | 5 | ||||
-rw-r--r-- | lib/trx_interface/trx_impl.cc | 69 | ||||
-rw-r--r-- | lib/trx_interface/trx_impl.h | 1 | ||||
-rw-r--r-- | lib/trx_interface/udp_socket.cc | 14 | ||||
-rw-r--r-- | lib/trx_interface/udp_socket.h | 6 |
5 files changed, 85 insertions, 10 deletions
diff --git a/grc/trx_interface/gsm_trx.xml b/grc/trx_interface/gsm_trx.xml index 71c88ef..f73b5fd 100644 --- a/grc/trx_interface/gsm_trx.xml +++ b/grc/trx_interface/gsm_trx.xml @@ -24,6 +24,11 @@ <type>message</type> </sink> + <source> + <name>bursts</name> + <type>message</type> + </source> + <doc> OsmoTRX like UDP interface for external applications. diff --git a/lib/trx_interface/trx_impl.cc b/lib/trx_interface/trx_impl.cc index abcd45e..48ef51a 100644 --- a/lib/trx_interface/trx_impl.cc +++ b/lib/trx_interface/trx_impl.cc @@ -30,6 +30,9 @@ #include "udp_socket.h" #include "trx_impl.h" +#define BURST_SIZE 148 +#define DATA_IF_MTU 160 + namespace gr { namespace grgsm { @@ -53,6 +56,9 @@ namespace gr { gr::io_signature::make(0, 0, 0)) { message_port_register_in(pmt::mp("bursts")); + message_port_register_out(pmt::mp("bursts")); + + // Bind a port handler set_msg_handler(pmt::mp("bursts"), boost::bind(&trx_impl::handle_dl_burst, this, _1)); @@ -62,9 +68,15 @@ namespace gr { std::string data_src_port = boost::lexical_cast<std::string> (base_port + 2); std::string data_dst_port = boost::lexical_cast<std::string> (base_port + 102); - // Init DATA interface - d_data_sock = new udp_socket(remote_addr, data_src_port, data_dst_port); - d_clck_sock = new udp_socket(remote_addr, clck_src_port, clck_dst_port); + // Init DATA & CLCK interfaces + d_data_sock = new udp_socket(remote_addr, + data_src_port, data_dst_port, DATA_IF_MTU); + d_clck_sock = new udp_socket(remote_addr, + clck_src_port, clck_dst_port, DATA_IF_MTU); + + // Bind DATA interface handler + d_data_sock->udp_rx_handler = boost::bind( + &trx_impl::handle_ul_burst, this, _1, _2); } /* @@ -156,5 +168,56 @@ namespace gr { d_data_sock->udp_send(buf, 158); } + void + trx_impl::handle_ul_burst(uint8_t *payload, size_t len) + { + // Check length according to the protocol + if (len != 154) + return; + + /* Make sure TS index is correct */ + if (payload[0] >= 8) + return; + + /* Unpack and check frame number */ + uint32_t fn = (payload[1] << 24) + | (payload[2] << 16) + | (payload[3] << 8) + | payload[4]; + + if (fn >= 2715648) + return; + + // Prepare a buffer for GSMTAP header and burst + uint8_t buf[sizeof(gsmtap_hdr) + BURST_SIZE]; + + // Set up pointer to GSMTAP header structure + struct gsmtap_hdr *header = (struct gsmtap_hdr *) buf; + memset(header, 0x00, sizeof(struct gsmtap_hdr)); + + // Fill in basic info + header->version = GSMTAP_VERSION; + header->hdr_len = sizeof(gsmtap_hdr) / 4; + header->type = GSMTAP_TYPE_UM_BURST; + + // Set timeslot index and frame number + header->timeslot = payload[0]; + header->frame_number = htobe32(fn); + + // HACK: use GSMTAP_BURST_NORMAL for now + // FIXME: We will need to distinguish between RACN and NORMAL + header->sub_type = GSMTAP_BURST_NORMAL; + + // Copy burst bits (0 & 1) for source message + memcpy(buf + sizeof(gsmtap_hdr), payload + 6, BURST_SIZE); + + // Create a pmt blob + pmt::pmt_t blob = pmt::make_blob(buf, sizeof(gsmtap_hdr) + BURST_SIZE); + pmt::pmt_t msg = pmt::cons(pmt::PMT_NIL, blob); + + /* Send a message to the output */ + message_port_pub(pmt::mp("bursts"), msg); + } + } /* namespace grgsm */ } /* namespace gr */ diff --git a/lib/trx_interface/trx_impl.h b/lib/trx_interface/trx_impl.h index 41a4788..29545b1 100644 --- a/lib/trx_interface/trx_impl.h +++ b/lib/trx_interface/trx_impl.h @@ -45,6 +45,7 @@ namespace gr { ~trx_impl(); void handle_dl_burst(pmt::pmt_t msg); + void handle_ul_burst(uint8_t *payload, size_t len); }; } // namespace grgsm diff --git a/lib/trx_interface/udp_socket.cc b/lib/trx_interface/udp_socket.cc index 4bbf206..be4bb66 100644 --- a/lib/trx_interface/udp_socket.cc +++ b/lib/trx_interface/udp_socket.cc @@ -40,8 +40,12 @@ namespace gr { udp_socket::udp_socket( const std::string &remote_addr, const std::string &src_port, - const std::string &dst_port) + const std::string &dst_port, + size_t mtu) { + // Resize receive buffer according to MTU value + d_rxbuf.resize(mtu); + // Resolve remote host address udp::resolver resolver(d_io_service); @@ -100,11 +104,9 @@ namespace gr { if (error) return; - pmt::pmt_t vector = pmt::init_u8vector(bytes_transferred, - (const uint8_t *) &d_rxbuf[0]); - pmt::pmt_t pdu = pmt::cons(pmt::PMT_NIL, vector); - - // TODO: call handler here + // Call incoming data handler + if (udp_rx_handler != NULL) + udp_rx_handler((uint8_t *) &d_rxbuf[0], bytes_transferred); d_udp_socket->async_receive_from( boost::asio::buffer(d_rxbuf), d_udp_endpoint_rx, diff --git a/lib/trx_interface/udp_socket.h b/lib/trx_interface/udp_socket.h index 2f424c9..5bcc42b 100644 --- a/lib/trx_interface/udp_socket.h +++ b/lib/trx_interface/udp_socket.h @@ -25,8 +25,10 @@ #include <gnuradio/thread/thread.h> +#include <boost/function.hpp> #include <boost/array.hpp> #include <boost/asio.hpp> +#include <boost/bind.hpp> #include <pmt/pmt.h> namespace gr { @@ -53,10 +55,12 @@ namespace gr { udp_socket( const std::string &remote_addr, const std::string &src_port, - const std::string &dst_port); + const std::string &dst_port, + size_t mtu); ~udp_socket(); void udp_send(uint8_t *data, size_t len); + boost::function<void (uint8_t *, size_t)> udp_rx_handler; }; } /* namespace blocks */ |