diff --git a/grc/demapping/gsm_bcch_ccch_demapper.xml b/grc/demapping/gsm_bcch_ccch_demapper.xml index f027f8e..b295ce1 100644 --- a/grc/demapping/gsm_bcch_ccch_demapper.xml +++ b/grc/demapping/gsm_bcch_ccch_demapper.xml @@ -3,7 +3,7 @@ BCCH + CCCH demapper gsm_bcch_ccch_demapper import grgsm - grgsm.universal_ctrl_chans_demapper($timeslot_nr, $starts_fn_mod51, $channel_types) + grgsm.universal_ctrl_chans_demapper($timeslot_nr, $downlink_starts_fn_mod51, $downlink_channel_types, $uplink_starts_fn_mod51, $uplink_channel_types) Timeslot @@ -14,21 +14,37 @@ - starts_fn_mod51 - starts_fn_mod51 + downlink_starts_fn_mod51 + downlink_starts_fn_mod51 [2,6,12,16,22,26,32,36,42,46] int_vector all - channel_types - channel_types + downlink_channel_types + downlink_channel_types [1,2,2,2,2,2,2,2,2,2] int_vector all + + uplink_starts_fn_mod51 + uplink_starts_fn_mod51 + [] + int_vector + all + + + + uplink_channel_types + uplink_channel_types + [] + int_vector + all + + bursts message diff --git a/grc/demapping/gsm_bcch_ccch_sdcch4_demapper.xml b/grc/demapping/gsm_bcch_ccch_sdcch4_demapper.xml index 80e67d5..90b33ce 100644 --- a/grc/demapping/gsm_bcch_ccch_sdcch4_demapper.xml +++ b/grc/demapping/gsm_bcch_ccch_sdcch4_demapper.xml @@ -3,7 +3,7 @@ BCCH + CCCH + SDCCH/4 demapper gsm_bcch_ccch_sdcch4_demapper import grgsm - grgsm.universal_ctrl_chans_demapper($timeslot_nr, $starts_fn_mod51, $channel_types) + grgsm.universal_ctrl_chans_demapper($timeslot_nr, $downlink_starts_fn_mod51, $downlink_channel_types, $uplink_starts_fn_mod51, $uplink_channel_types) Timeslot @@ -14,21 +14,37 @@ - starts_fn_mod51 - starts_fn_mod51 + downlink_starts_fn_mod51 + downlink_starts_fn_mod51 [2,6,12,16,22,26,32,36,42,46] int_vector all - channel_types - channel_types + downlink_channel_types + downlink_channel_types [1,2,2,2,7,7,7,7,135,135] int_vector all + + uplink_starts_fn_mod51 + uplink_starts_fn_mod51 + [0,6,10,37,41,47] + int_vector + all + + + + uplink_channel_types + uplink_channel_types + [7,135,135,7,7,7] + int_vector + all + + bursts message diff --git a/grc/demapping/gsm_sdcch8_demapper.xml b/grc/demapping/gsm_sdcch8_demapper.xml index 38a8112..c81032a 100644 --- a/grc/demapping/gsm_sdcch8_demapper.xml +++ b/grc/demapping/gsm_sdcch8_demapper.xml @@ -3,7 +3,7 @@ SDCCH/8 demapper gsm_sdcch8_demapper import grgsm - grgsm.universal_ctrl_chans_demapper($timeslot_nr, $starts_fn_mod51, $channel_types) + grgsm.universal_ctrl_chans_demapper($timeslot_nr, $downlink_starts_fn_mod51, $downlink_channel_types, $uplink_starts_fn_mod51, $uplink_channel_types) Timeslot @@ -14,16 +14,32 @@ - starts_fn_mod51 - starts_fn_mod51 + downlink_starts_fn_mod51 + downlink_starts_fn_mod51 [0,4,8,12,16,20,24,28,32,36,40,44] int_vector all - channel_types - channel_types + downlink_channel_types + downlink_channel_types + [8,8,8,8,8,8,8,8,136,136,136,136] + int_vector + all + + + + uplink_starts_fn_mod51 + uplink_starts_fn_mod51 + [15,19,23,27,31,35,39,43,47,0,4,8] + int_vector + all + + + + uplink_channel_types + uplink_channel_types [8,8,8,8,8,8,8,8,136,136,136,136] int_vector all @@ -42,4 +58,4 @@ Demapper for SDCCH/8 + SACCH/C8 control channels. This corresponds to channel combination vii specified in GSM 05.02, section 6.4 - \ No newline at end of file + diff --git a/grc/demapping/gsm_universal_ctrl_chans_demapper.xml b/grc/demapping/gsm_universal_ctrl_chans_demapper.xml index 1d8d202..3b522be 100644 --- a/grc/demapping/gsm_universal_ctrl_chans_demapper.xml +++ b/grc/demapping/gsm_universal_ctrl_chans_demapper.xml @@ -3,7 +3,7 @@ Universal ctrl chans demapper gsm_universal_ctrl_chans_demapper import grgsm - grgsm.universal_ctrl_chans_demapper($timeslot_nr, $starts_fn_mod51, $channel_types) + grgsm.universal_ctrl_chans_demapper($timeslot_nr, $downlink_starts_fn_mod51, $downlink_channel_types, $uplink_starts_fn_mod51, $uplink_channel_types) timeslot_nr @@ -14,21 +14,37 @@ - starts_fn_mod51 - starts_fn_mod51 + downlink_starts_fn_mod51 + downlink_starts_fn_mod51 [2,6,12,16,22,26,32,36,42,46] int_vector part - channel_types - channel_types + downlink_channel_types + downlink_channel_types [1,2,2,2,2,2,2,2,2,2] int_vector part + + uplink_starts_fn_mod51 + uplink_starts_fn_mod51 + [0,6,10,37,41,47] + int_vector + part + + + + uplink_channel_types + uplink_channel_types + [2,2,2,2,2,2] + int_vector + part + + bursts message @@ -37,4 +53,7 @@ bursts message + + Universal demapper for control channels. + diff --git a/grc/gsm_block_tree.xml b/grc/gsm_block_tree.xml index f49f055..0b15562 100644 --- a/grc/gsm_block_tree.xml +++ b/grc/gsm_block_tree.xml @@ -13,6 +13,7 @@ Receiver gsm_receiver + gsm_receiver_with_uplink gsm_cx_channel_hopper gsm_fcch_burst_tagger gsm_sch_detector diff --git a/grc/receiver/CMakeLists.txt b/grc/receiver/CMakeLists.txt index af7042d..bbc086f 100644 --- a/grc/receiver/CMakeLists.txt +++ b/grc/receiver/CMakeLists.txt @@ -21,6 +21,7 @@ install(FILES gsm_input.xml gsm_wideband_input.xml gsm_receiver.xml + gsm_receiver_with_uplink.xml gsm_fcch_burst_tagger.xml gsm_sch_detector.xml gsm_fcch_detector.xml diff --git a/grc/receiver/gsm_receiver.xml b/grc/receiver/gsm_receiver.xml index 2119fd2..2988243 100644 --- a/grc/receiver/gsm_receiver.xml +++ b/grc/receiver/gsm_receiver.xml @@ -3,7 +3,7 @@ GSM Receiver gsm_receiver import grgsm - grgsm.receiver($osr, $cell_allocation, $tseq_nums) + grgsm.receiver($osr, $cell_allocation, $tseq_nums, False) Oversampling ratio diff --git a/grc/receiver/gsm_receiver_with_uplink.xml b/grc/receiver/gsm_receiver_with_uplink.xml new file mode 100644 index 0000000..4b68336 --- /dev/null +++ b/grc/receiver/gsm_receiver_with_uplink.xml @@ -0,0 +1,71 @@ + + + GSM Receiver (with uplink) + gsm_receiver_with_uplink + import grgsm + grgsm.receiver($osr, $cell_allocation, $tseq_nums, True) + + + Oversampling ratio + osr + 4 + int + + + + Cell allocation + cell_allocation + [0] + float_vector + part + + + + TSEQ numbers + tseq_nums + [] + int_vector + part + + + + Num Streams + num_streams + 1 + int + part + + + $num_streams >= 0 + + + C + complex + $num_streams + + + + + C_up + complex + $num_streams + + + + C0 + message + 1 + + + + CX + message + 1 + + + + measurements + message + 1 + + diff --git a/include/grgsm/demapping/universal_ctrl_chans_demapper.h b/include/grgsm/demapping/universal_ctrl_chans_demapper.h index d8114f7..9d7240c 100644 --- a/include/grgsm/demapping/universal_ctrl_chans_demapper.h +++ b/include/grgsm/demapping/universal_ctrl_chans_demapper.h @@ -49,7 +49,7 @@ namespace gr { * class. gsm::universal_ctrl_chans_demapper::make is the public interface for * creating new instances. */ - static sptr make(unsigned int timeslot_nr, const std::vector &starts_fn_mod51, const std::vector &channel_types); + static sptr make(unsigned int timeslot_nr, const std::vector &downlink_starts_fn_mod51, const std::vector &downlink_channel_types, const std::vector &uplink_starts_fn_mod51, const std::vector &uplink_channel_types); }; } // namespace gsm diff --git a/include/grgsm/receiver/receiver.h b/include/grgsm/receiver/receiver.h index 80124f7..00e749e 100644 --- a/include/grgsm/receiver/receiver.h +++ b/include/grgsm/receiver/receiver.h @@ -51,7 +51,7 @@ namespace gr { * class. gsm::receiver::make is the public interface for * creating new instances. */ - static sptr make(int osr, const std::vector &cell_allocation, const std::vector &seq_nums); + static sptr make(int osr, const std::vector &cell_allocation, const std::vector &seq_nums, bool process_uplink); virtual void set_cell_allocation(const std::vector &cell_allocation) = 0; virtual void set_tseq_nums(const std::vector & tseq_nums) = 0; diff --git a/lib/demapping/universal_ctrl_chans_demapper_impl.cc b/lib/demapping/universal_ctrl_chans_demapper_impl.cc index c711928..cbbbc32 100644 --- a/lib/demapping/universal_ctrl_chans_demapper_impl.cc +++ b/lib/demapping/universal_ctrl_chans_demapper_impl.cc @@ -36,16 +36,16 @@ namespace gr { namespace gsm { universal_ctrl_chans_demapper::sptr - universal_ctrl_chans_demapper::make(unsigned int timeslot_nr, const std::vector &starts_fn_mod51, const std::vector &channel_types) + universal_ctrl_chans_demapper::make(unsigned int timeslot_nr, const std::vector &downlink_starts_fn_mod51, const std::vector &downlink_channel_types, const std::vector &uplink_starts_fn_mod51, const std::vector &uplink_channel_types) { return gnuradio::get_initial_sptr - (new universal_ctrl_chans_demapper_impl(timeslot_nr, starts_fn_mod51, channel_types)); + (new universal_ctrl_chans_demapper_impl(timeslot_nr, downlink_starts_fn_mod51, downlink_channel_types, uplink_starts_fn_mod51, uplink_channel_types)); } /* * The private constructor */ - universal_ctrl_chans_demapper_impl::universal_ctrl_chans_demapper_impl(unsigned int timeslot_nr, const std::vector &starts_fn_mod51, const std::vector &channel_types) + universal_ctrl_chans_demapper_impl::universal_ctrl_chans_demapper_impl(unsigned int timeslot_nr, const std::vector &downlink_starts_fn_mod51, const std::vector &downlink_channel_types, const std::vector &uplink_starts_fn_mod51, const std::vector &uplink_channel_types) : gr::block("universal_ctrl_chans_demapper", gr::io_signature::make(0, 0, 0), gr::io_signature::make(0, 0, 0)), @@ -56,75 +56,137 @@ namespace gr { for(int ii=0; ii<51; ii++) { - d_starts_fn_mod51[ii]=0; - d_channel_types[ii]=0; - d_subslots[ii] = 0; - d_subslots[ii+51] = 0; + d_downlink_starts_fn_mod51[ii]=0; + d_downlink_channel_types[ii]=0; + d_downlink_subslots[ii] = 0; + d_downlink_subslots[ii+51] = 0; + + d_uplink_starts_fn_mod51[ii]=0; + d_uplink_channel_types[ii]=0; + d_uplink_subslots[ii] = 0; + d_uplink_subslots[ii+51] = 0; } std::vector::const_iterator s; std::vector::const_iterator ch_type; - for(s=starts_fn_mod51.begin(), ch_type=channel_types.begin();s != starts_fn_mod51.end(); s++) + for(s=downlink_starts_fn_mod51.begin(), ch_type=downlink_channel_types.begin();s != downlink_starts_fn_mod51.end(); s++) { if((*s >= 0) and (*s <= (51-4))) { for(int ii=0; ii<4; ii++){ - d_starts_fn_mod51[*s+ii] = *s; - if(ch_type!=channel_types.end()) + d_downlink_starts_fn_mod51[*s+ii] = *s; + if(ch_type!=downlink_channel_types.end()) { - d_channel_types[*s+ii] = *ch_type; + d_downlink_channel_types[*s+ii] = *ch_type; } } - if(ch_type!=channel_types.end()) + if(ch_type!=downlink_channel_types.end()) { ch_type++; } } } - std::set distinct_channels(channel_types.begin(), channel_types.end()); - std::set::iterator it; - unsigned int subslot; - - for (it=distinct_channels.begin(); it != distinct_channels.end(); it++) - { - subslot = 0; - for(s=starts_fn_mod51.begin();s != starts_fn_mod51.end(); s++) - { - if ((d_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4))) - { - for(int ii=0; ii<4; ii++) - { - d_subslots[*s+ii] = subslot; - d_subslots[*s+ii+51] = subslot; - } - subslot++; - } - } - - if (*it == GSMTAP_CHANNEL_ACCH or - *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH) or - *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH4) or - *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH8) or - *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_F) or - *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_H) - ) - { - for(s=starts_fn_mod51.begin();s != starts_fn_mod51.end(); s++) - { - if ((d_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4))) - { - for(int ii=0; ii<4; ii++) - { - d_subslots[*s+ii+51] = subslot; - } - subslot++; - } - } - } - } + for(s=uplink_starts_fn_mod51.begin(), ch_type=uplink_channel_types.begin();s != uplink_starts_fn_mod51.end(); s++) + { + if((*s >= 0) and (*s <= (51-4))) + { + for(int ii=0; ii<4; ii++){ + d_uplink_starts_fn_mod51[*s+ii] = *s; + if(ch_type!=uplink_channel_types.end()) + { + d_uplink_channel_types[*s+ii] = *ch_type; + } + } + if(ch_type!=uplink_channel_types.end()) + { + ch_type++; + } + } + } + std::set distinct_downlink_channels(downlink_channel_types.begin(), downlink_channel_types.end()); + std::set::iterator it; + unsigned int subslot; + + for (it=distinct_downlink_channels.begin(); it != distinct_downlink_channels.end(); it++) + { + subslot = 0; + for(s=downlink_starts_fn_mod51.begin();s != downlink_starts_fn_mod51.end(); s++) + { + if ((d_downlink_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4))) + { + for(int ii=0; ii<4; ii++) + { + d_downlink_subslots[*s+ii] = subslot; + d_downlink_subslots[*s+ii+51] = subslot; + } + subslot++; + } + } + + if (*it == GSMTAP_CHANNEL_ACCH or + *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH) or + *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH4) or + *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH8) or + *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_F) or + *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_H) + ) + { + for(s=downlink_starts_fn_mod51.begin();s != downlink_starts_fn_mod51.end(); s++) + { + if ((d_downlink_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4))) + { + for(int ii=0; ii<4; ii++) + { + d_downlink_subslots[*s+ii+51] = subslot; + } + subslot++; + } + } + } + } + + std::set distinct_uplink_channels(uplink_channel_types.begin(), uplink_channel_types.end()); + for (it=distinct_uplink_channels.begin(); it != distinct_uplink_channels.end(); it++) + { + subslot = 0; + for(s=uplink_starts_fn_mod51.begin();s != uplink_starts_fn_mod51.end(); s++) + { + if ((d_uplink_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4))) + { + for(int ii=0; ii<4; ii++) + { + d_uplink_subslots[*s+ii] = subslot; + d_uplink_subslots[*s+ii+51] = subslot; + } + subslot++; + } + } + + if (*it == GSMTAP_CHANNEL_ACCH or + *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH) or + *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH4) or + *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_SDCCH8) or + *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_F) or + *it == (GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_H) + ) + { + for(s=uplink_starts_fn_mod51.begin();s != uplink_starts_fn_mod51.end(); s++) + { + if ((d_uplink_channel_types[*s] == *it) and (*s >= 0) and (*s <= (51-4))) + { + for(int ii=0; ii<4; ii++) + { + d_uplink_subslots[*s+ii+51] = subslot; + } + subslot++; + } + } + } + } + message_port_register_in(pmt::mp("bursts")); set_msg_handler(pmt::mp("bursts"), boost::bind(&universal_ctrl_chans_demapper_impl::filter_ctrl_chans, this, _1)); @@ -142,52 +204,102 @@ namespace gr { { pmt::pmt_t header_plus_burst = pmt::cdr(msg); gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(header_plus_burst); - + uint32_t frame_nr = be32toh(header->frame_number); uint32_t fn_mod51 = frame_nr % 51; - uint32_t fn51_start = d_starts_fn_mod51[fn_mod51]; - uint32_t fn51_stop = fn51_start + 3; - uint32_t ch_type = d_channel_types[fn_mod51]; + bool uplink_burst = (be16toh(header->arfcn) & 0x4000) ? true : false; + if(header->timeslot==d_timeslot){ int8_t new_msg[sizeof(gsmtap_hdr)+BURST_SIZE]; gsmtap_hdr * new_hdr = (gsmtap_hdr*)new_msg; memcpy(new_msg, header, sizeof(gsmtap_hdr)+BURST_SIZE); - new_hdr->sub_type = ch_type; - new_hdr->sub_slot = d_subslots[fn_mod51 + (51 * (frame_nr % 2))]; pmt::pmt_t msg_binary_blob = pmt::make_blob(new_msg,sizeof(gsmtap_hdr)+BURST_SIZE); pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, msg_binary_blob); - if(fn_mod51>=fn51_start && fn_mod51<=fn51_stop) + if(uplink_burst) { - uint32_t ii = fn_mod51 - fn51_start; - d_frame_numbers[ii] = frame_nr; - d_bursts[ii] = msg_out; - } - - if(fn_mod51==fn51_stop) - { - //check for a situation where some bursts were lost - //in this situation frame numbers won't be consecutive - bool frames_are_consecutive = true; - for(int jj=1; jj<4; jj++) + uint32_t fn51_start = d_uplink_starts_fn_mod51[fn_mod51]; + uint32_t fn51_stop = fn51_start + 3; + uint32_t ch_type = d_uplink_channel_types[fn_mod51]; + + if(ch_type != 0) { - if((d_frame_numbers[jj]-d_frame_numbers[jj-1])!=1) - { - frames_are_consecutive = false; - } + new_hdr->sub_type = ch_type; } - if(frames_are_consecutive) + new_hdr->sub_slot = d_uplink_subslots[fn_mod51 + (51 * (frame_nr % 2))]; + + if(fn_mod51>=fn51_start && fn_mod51<=fn51_stop) { - //send bursts to the output - for(int jj=0; jj<4; jj++) + uint32_t ii = fn_mod51 - fn51_start; + d_uplink_frame_numbers[ii] = frame_nr; + d_uplink_bursts[ii] = msg_out; + } + + if(fn_mod51==fn51_stop) + { + //check for a situation where some bursts were lost + //in this situation frame numbers won't be consecutive + bool frames_are_consecutive = true; + for(int jj=1; jj<4; jj++) { - message_port_pub(pmt::mp("bursts"), d_bursts[jj]); + if((d_uplink_frame_numbers[jj]-d_uplink_frame_numbers[jj-1])!=1) + { + frames_are_consecutive = false; + } } - } + if(frames_are_consecutive) + { + //send bursts to the output + for(int jj=0; jj<4; jj++) + { + message_port_pub(pmt::mp("bursts"), d_uplink_bursts[jj]); + } + } + } + } + else + { + uint32_t fn51_start = d_downlink_starts_fn_mod51[fn_mod51]; + uint32_t fn51_stop = fn51_start + 3; + uint32_t ch_type = d_downlink_channel_types[fn_mod51]; + + if(ch_type != 0) + { + new_hdr->sub_type = ch_type; + } + new_hdr->sub_slot = d_downlink_subslots[fn_mod51 + (51 * (frame_nr % 2))]; + + if(fn_mod51>=fn51_start && fn_mod51<=fn51_stop) + { + uint32_t ii = fn_mod51 - fn51_start; + d_downlink_frame_numbers[ii] = frame_nr; + d_downlink_bursts[ii] = msg_out; + } + + if(fn_mod51==fn51_stop) + { + //check for a situation where some bursts were lost + //in this situation frame numbers won't be consecutive + bool frames_are_consecutive = true; + for(int jj=1; jj<4; jj++) + { + if((d_downlink_frame_numbers[jj]-d_downlink_frame_numbers[jj-1])!=1) + { + frames_are_consecutive = false; + } + } + if(frames_are_consecutive) + { + //send bursts to the output + for(int jj=0; jj<4; jj++) + { + message_port_pub(pmt::mp("bursts"), d_downlink_bursts[jj]); + } + } + } } } } } /* namespace gsm */ } /* namespace gr */ - diff --git a/lib/demapping/universal_ctrl_chans_demapper_impl.h b/lib/demapping/universal_ctrl_chans_demapper_impl.h index d4e1440..0316bf4 100644 --- a/lib/demapping/universal_ctrl_chans_demapper_impl.h +++ b/lib/demapping/universal_ctrl_chans_demapper_impl.h @@ -32,14 +32,19 @@ namespace gr { class universal_ctrl_chans_demapper_impl : public universal_ctrl_chans_demapper { private: - unsigned int d_starts_fn_mod51[51]; - unsigned int d_channel_types[51]; - unsigned int d_subslots[102]; + unsigned int d_downlink_starts_fn_mod51[51]; + unsigned int d_uplink_starts_fn_mod51[51]; + unsigned int d_downlink_channel_types[51]; + unsigned int d_uplink_channel_types[51]; + unsigned int d_downlink_subslots[102]; + unsigned int d_uplink_subslots[102]; unsigned int d_timeslot; - uint32_t d_frame_numbers[4]; - pmt::pmt_t d_bursts[4]; + uint32_t d_downlink_frame_numbers[4]; + uint32_t d_uplink_frame_numbers[4]; + pmt::pmt_t d_downlink_bursts[4]; + pmt::pmt_t d_uplink_bursts[4]; public: - universal_ctrl_chans_demapper_impl(unsigned int timeslot_nr, const std::vector &starts_fn_mod51, const std::vector &channel_types); + universal_ctrl_chans_demapper_impl(unsigned int timeslot_nr, const std::vector &downlink_starts_fn_mod51, const std::vector &downlink_channel_types, const std::vector &uplink_starts_fn_mod51, const std::vector &uplink_channel_types); ~universal_ctrl_chans_demapper_impl(); void filter_ctrl_chans(pmt::pmt_t msg); diff --git a/lib/receiver/receiver_config.cc b/lib/receiver/receiver_config.cc index c8b85c7..0abf200 100644 --- a/lib/receiver/receiver_config.cc +++ b/lib/receiver/receiver_config.cc @@ -46,6 +46,33 @@ burst_counter & burst_counter::operator++(int) return (*this); } +burst_counter burst_counter::subtract_timeslots(unsigned int number_of_timeslots) +{ + int timeslot_nr = (int)d_timeslot_nr - (int)number_of_timeslots; + int t1,t2,t3; + if (timeslot_nr < 0) { + timeslot_nr = timeslot_nr + 8; + + t2 = (d_t2 - 1) % 26; + t3 = (d_t3 - 1) % 51; + + if ((d_t2 == 0) && (d_t3 == 0)) { + t1 = (d_t1 - 1) % (1 << 11); + } else + { + t1 = d_t1; + } + } + else + { + t1 = d_t1; + t2 = d_t2; + t3 = d_t3; + } + + return burst_counter(d_OSR, t1, t2, t3, timeslot_nr); +} + void burst_counter::set(uint32_t t1, uint32_t t2, uint32_t t3, uint32_t timeslot_nr) { d_t1 = t1; diff --git a/lib/receiver/receiver_config.h b/lib/receiver/receiver_config.h index 496e1fe..17b98c8 100644 --- a/lib/receiver/receiver_config.h +++ b/lib/receiver/receiver_config.h @@ -89,12 +89,14 @@ class burst_counter d_t3(t3), d_timeslot_nr(timeslot_nr), d_offset_fractional(0.0), - d_offset_integer(0.0) { + d_offset_integer(0.0) + { d_offset_integer = 0; d_offset_fractional = 0; } burst_counter & operator++(int); + burst_counter subtract_timeslots(unsigned int number_of_timeslots); void set(uint32_t t1, uint32_t t2, uint32_t t3, uint32_t timeslot_nr); uint32_t get_t1() { diff --git a/lib/receiver/receiver_impl.cc b/lib/receiver/receiver_impl.cc index bd2b306..09a3703 100644 --- a/lib/receiver/receiver_impl.cc +++ b/lib/receiver/receiver_impl.cc @@ -52,20 +52,21 @@ namespace gr namespace gsm { receiver::sptr -receiver::make(int osr, const std::vector &cell_allocation, const std::vector &tseq_nums) +receiver::make(int osr, const std::vector &cell_allocation, const std::vector &tseq_nums, bool process_uplink) { return gnuradio::get_initial_sptr - (new receiver_impl(osr, cell_allocation, tseq_nums)); + (new receiver_impl(osr, cell_allocation, tseq_nums, process_uplink)); } /* * The private constructor */ -receiver_impl::receiver_impl(int osr, const std::vector &cell_allocation, const std::vector &tseq_nums) +receiver_impl::receiver_impl(int osr, const std::vector &cell_allocation, const std::vector &tseq_nums, bool process_uplink) : gr::sync_block("receiver", gr::io_signature::make(1, -1, sizeof(gr_complex)), gr::io_signature::make(0, 0, 0)), d_OSR(osr), + d_process_uplink(process_uplink), d_chan_imp_length(CHAN_IMP_RESP_LENGTH), d_counter(0), d_fcch_start_pos(0), @@ -172,7 +173,7 @@ receiver_impl::work(int noutput_items, { burst_start = get_sch_chan_imp_resp(input, &channel_imp_resp[0]); //get channel impulse response from it detect_burst(input, &channel_imp_resp[0], burst_start, output_binary); //detect bits using MLSE detection - if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0) //decode SCH burst + if (decode_sch(&output_binary[3], &t1, &t2, &t3, &d_ncc, &d_bcc) == 0) //decode SCH burst { d_burst_nr.set(t1, t2, t3, 0); //set counter of bursts value d_burst_nr++; @@ -198,10 +199,15 @@ receiver_impl::work(int noutput_items, int offset = 0; int to_consume = 0; unsigned char output_binary[BURST_SIZE]; - burst_type b_type; + unsigned int inputs_to_process=d_cell_allocation.size(); - for(int input_nr=0; input_nrversion = GSMTAP_VERSION; tap_header->hdr_len = sizeof(gsmtap_hdr)/4; tap_header->type = GSMTAP_TYPE_UM_BURST; - tap_header->timeslot = static_cast(d_burst_nr.get_timeslot_nr()); - tap_header->frame_number = htobe32(d_burst_nr.get_frame_nr()); tap_header->sub_type = burst_type; - tap_header->arfcn = htobe16(d_cell_allocation[input_nr]) ; + bool uplink_burst = (input_nr >= d_cell_allocation.size()); + if(!uplink_burst) // downlink burst + { + tap_header->timeslot = static_cast(d_burst_nr.get_timeslot_nr()); + tap_header->frame_number = htobe32(d_burst_nr.get_frame_nr()); + tap_header->arfcn = htobe16(d_cell_allocation[input_nr]) ; + } + else //uplink burst + { + tap_header->timeslot = static_cast(d_burst_nr.subtract_timeslots(3).get_timeslot_nr()); + tap_header->frame_number = htobe32(d_burst_nr.subtract_timeslots(3).get_frame_nr()); + input_nr = input_nr - d_cell_allocation.size(); + tap_header->arfcn = htobe16(d_cell_allocation[input_nr] | 0x4000); + } tap_header->signal_dbm = static_cast(d_signal_dbm); tap_header->snr_db = 0; diff --git a/lib/receiver/receiver_impl.h b/lib/receiver/receiver_impl.h index d668e14..c8d71f9 100644 --- a/lib/receiver/receiver_impl.h +++ b/lib/receiver/receiver_impl.h @@ -39,6 +39,7 @@ namespace gr { /**@name Configuration of the receiver */ //@{ const int d_OSR; ///< oversampling ratio + bool d_process_uplink; const int d_chan_imp_length; ///< channel impulse length float d_signal_dbm; std::vector d_tseq_nums; ///< stores training sequence numbers for channels different than C0 @@ -203,7 +204,7 @@ namespace gr { public: - receiver_impl(int osr, const std::vector &cell_allocation, const std::vector &tseq_nums); + receiver_impl(int osr, const std::vector &cell_allocation, const std::vector &tseq_nums, bool process_uplink); ~receiver_impl(); int work(int noutput_items, gr_vector_const_void_star &input_items, gr_vector_void_star &output_items);