/* -*- c++ -*- */
/*
 * @file
 * @author Piotr Krysik <ptrkrysik@gmail.com>
 * @section LICENSE
 *
 * Gr-gsm is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 3, or (at your option)
 * any later version.
 *
 * Gr-gsm is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with gr-gsm; see the file COPYING.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street,
 * Boston, MA 02110-1301, USA.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <gnuradio/io_signature.h>
#include "tch_f_chans_demapper_impl.h"
#include <grgsm/endian.h>
#include <grgsm/gsmtap.h>

namespace gr {
  namespace gsm {

    tch_f_chans_demapper::sptr
    tch_f_chans_demapper::make(unsigned int timeslot_nr)
    {
      return gnuradio::get_initial_sptr
        (new tch_f_chans_demapper_impl(timeslot_nr));
    }

    /*
     * The private constructor
     *
     */
    tch_f_chans_demapper_impl::tch_f_chans_demapper_impl(unsigned int timeslot_nr)
      : gr::block("tch_f_chans_demapper",
              gr::io_signature::make(0, 0, 0),
              gr::io_signature::make(0, 0, 0)),
       d_timeslot(timeslot_nr)

    {
        for (int ii=0; ii<3; ii++)
        {
            d_bursts_stolen[ii] = false;
        }

        message_port_register_in(pmt::mp("bursts"));
        set_msg_handler(pmt::mp("bursts"), boost::bind(&tch_f_chans_demapper_impl::filter_tch_chans, this, _1));
        message_port_register_out(pmt::mp("tch_bursts"));
        message_port_register_out(pmt::mp("acch_bursts"));
    }

    /*
     * Our virtual destructor.
     */
    tch_f_chans_demapper_impl::~tch_f_chans_demapper_impl()
    {
    }

    void tch_f_chans_demapper_impl::filter_tch_chans(pmt::pmt_t msg)
    {
        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_mod26 = frame_nr % 26;
        uint32_t fn_mod13 = frame_nr % 13;
        bool frames_are_consecutive = true;
        int8_t * burst_bits = (int8_t *)(pmt::blob_data(header_plus_burst))+sizeof(gsmtap_hdr);

        if(header->timeslot == d_timeslot){
            header->sub_type = GSMTAP_CHANNEL_TCH_F;

            if (fn_mod13 == 12)
            {
                header->sub_type = GSMTAP_CHANNEL_ACCH|GSMTAP_CHANNEL_TCH_F;

                // position of SACCH burst based on timeslot
                // see specification gsm 05.02
                uint32_t index;
                bool is_sacch = false;

                if (d_timeslot % 2 == 0 && fn_mod26 == 12)
                {
                    index = (((frame_nr - 12) / 26) - (d_timeslot / 2)) % 4;
                    is_sacch = true;
                }
                else if (d_timeslot % 2 == 1 && fn_mod26 == 25)
                {
                    index = (((frame_nr - 25) / 26) - ((d_timeslot - 1) / 2)) % 4;
                    is_sacch = true;
                }

                if (is_sacch)
                {
                    d_bursts_sacch[index] = msg;
                    d_frame_numbers_sacch[index] = frame_nr;

                    if (index == 3)
                    {
                        //check for a situation where some bursts were lost
                        //in this situation frame numbers won't be consecutive
                        frames_are_consecutive = true;
                        for(int jj=1; jj<4; jj++)
                        {
                            if((d_frame_numbers_sacch[jj]-d_frame_numbers_sacch[jj-1]) != 26)
                            {
                                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("acch_bursts"), d_bursts_sacch[jj]);
                            }
                        }
                    }
                }
            }
            else
            {
                if (fn_mod13 <= 3)
                {
                    // add to b1 and b3
                    d_bursts[0][fn_mod13] = msg;
                    d_bursts[2][fn_mod13 + 4] = msg;

                    // set framenumber
                    d_frame_numbers[0][fn_mod13] = frame_nr;
                    d_frame_numbers[2][fn_mod13 + 4] = frame_nr;
                }
                else if (fn_mod13 >= 4 && fn_mod13 <= 7)
                {
                    // add to b1 and b2
                    d_bursts[0][fn_mod13] = msg;
                    d_bursts[1][fn_mod13 - 4] = msg;

                    // set framenumber
                    d_frame_numbers[0][fn_mod13] = frame_nr;
                    d_frame_numbers[1][fn_mod13 - 4] = frame_nr;
                }
                else if (fn_mod13 >= 8 && fn_mod13 <= 11)
                {
                    // add to b2 and b3
                    d_bursts[1][fn_mod13 - 4] = msg;
                    d_bursts[2][fn_mod13 - 8] = msg;

                    // set framenumber
                    d_frame_numbers[1][fn_mod13 - 4] = frame_nr;
                    d_frame_numbers[2][fn_mod13 - 8] = frame_nr;
                }

                // send burst 1 or burst 2 to output
                if (fn_mod13 == 3 || fn_mod13 == 7 || fn_mod13 == 11)
                {
                    int tch_burst_nr = 0;

                    if (fn_mod13 == 11)
                    {
                        tch_burst_nr = 1;
                    }
                    else if (fn_mod13 == 3)
                    {
                        tch_burst_nr = 2;
                    }

                    //check for a situation where some bursts were lost
                    //in this situation frame numbers won't be consecutive
                    frames_are_consecutive = true;

                    for(int jj=1; jj<8; jj++)
                    {
                        if((d_frame_numbers[tch_burst_nr][jj] - d_frame_numbers[tch_burst_nr][jj-1]) != 1)
                        {
                            frames_are_consecutive = false;
                            // burst 3 has 1 sacch burst in between
                            if (tch_burst_nr == 2 && jj == 4
                                && d_frame_numbers[tch_burst_nr][jj] - d_frame_numbers[tch_burst_nr][jj - 1] == 2)
                            {
                                frames_are_consecutive = true;
                            }
                        }
                    }

                    if(frames_are_consecutive)
                    {
                        //send bursts to the output
                        for(int jj=0; jj<8; jj++)
                        {
                            message_port_pub(pmt::mp("tch_bursts"), d_bursts[tch_burst_nr][jj]);
                        }
                        d_bursts_stolen[tch_burst_nr] = false;
                    }
                }
            }
        }
    }
  } /* namespace gsm */
} /* namespace gr */

