/* -*- c++ -*- */
/*
 * @file
 * @author Roman Khassraf <rkhassraf@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 <grgsm/gsmtap.h>
#include "stdio.h"
#include "tch_f_decoder_impl.h"

#define DATA_BYTES 23

namespace gr {
  namespace gsm {

    tch_f_decoder::sptr
    tch_f_decoder::make(tch_mode mode, const std::string &file)
    {
      return gnuradio::get_initial_sptr
        (new tch_f_decoder_impl(mode, file));
    }

    /*
     * Constructor
     */
    tch_f_decoder_impl::tch_f_decoder_impl(tch_mode mode, const std::string &file)
      : gr::block("tch_f_decoder",
              gr::io_signature::make(0, 0, 0),
              gr::io_signature::make(0, 0, 0)),
      d_tch_mode(mode),
      d_collected_bursts_num(0),
      mBlockCoder(0x10004820009ULL, 40, 224),
      mU(228),
      mP(mU.segment(184,40)), mD(mU.head(184)), mDP(mU.head(224)),
      mC(CONV_SIZE),
      mClass1_c(mC.head(378)),
      mClass2_c(mC.segment(378, 78)),
      mTCHU(189),
      mTCHD(260),
      mClass1A_d(mTCHD.head(50))
    {
        d_speech_file = fopen( file.c_str(), "wb" );
        if (d_speech_file == NULL)
        {
            throw std::runtime_error("TCH/F Decoder: can't open file\n");
        }

        if (d_tch_mode != TCH_FS)
        {
            fwrite(amr_nb_magic, 1, 6, d_speech_file);
        }

        int j, k, B;
        for (k = 0; k < CONV_SIZE; k++)
        {
            B = k % 8;
            j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
            interleave_trans[k] = B * 114 + j;
        }

        //setup input/output ports
        message_port_register_in(pmt::mp("bursts"));
        set_msg_handler(pmt::mp("bursts"), boost::bind(&tch_f_decoder_impl::decode, this, _1));
        message_port_register_out(pmt::mp("msgs"));
    }

    tch_f_decoder_impl::~tch_f_decoder_impl()
    {
    }

    void tch_f_decoder_impl::decode(pmt::pmt_t msg)
    {
        d_bursts[d_collected_bursts_num] = msg;
        d_collected_bursts_num++;

        bool stolen = false;

        if (d_collected_bursts_num == 8)
        {
            d_collected_bursts_num = 0;

            // reorganize data
            for (int ii = 0; ii < 8; ii++)
            {
                pmt::pmt_t header_plus_burst = pmt::cdr(d_bursts[ii]);
                int8_t * burst_bits = (int8_t *)(pmt::blob_data(header_plus_burst))+sizeof(gsmtap_hdr);

                for (int jj = 0; jj < 57; jj++)
                {
                    iBLOCK[ii*114+jj] = burst_bits[jj + 3];
                    iBLOCK[ii*114+jj+57] = burst_bits[jj + 88]; //88 = 3+57+1+26+1
                }

                if ((ii <= 3 && static_cast<int>(burst_bits[87]) == 1) || (ii >= 4 && static_cast<int>(burst_bits[60]) == 1))
                {
                    stolen = true;
                }
            }

            // deinterleave
            for (int k = 0; k < CONV_SIZE; k++)
            {
                mC[k] = iBLOCK[interleave_trans[k]];
            }

            // Decode stolen frames as FACCH/F
            if (stolen)
            {
                mVR204Coder.decode(mC, mU);
                mP.invert();

                unsigned syndrome = mBlockCoder.syndrome(mDP);

                if (syndrome == 0)
                {
                    unsigned char outmsg[27];
                    unsigned char sbuf_len=224;
                    int i, j, c, pos=0;
                    for(i = 0; i < sbuf_len; i += 8) {
                        for(j = 0, c = 0; (j < 8) && (i + j < sbuf_len); j++){
                            c |= (!!mU.bit(i + j)) << j;
                        }
                        outmsg[pos++] = c & 0xff;
                    }

                    pmt::pmt_t first_header_plus_burst = pmt::cdr(d_bursts[0]);
                    gsmtap_hdr * header = (gsmtap_hdr *)pmt::blob_data(first_header_plus_burst);
                    header->type = GSMTAP_TYPE_UM;
                    int8_t * header_content = (int8_t *)header;
                    int8_t header_plus_data[sizeof(gsmtap_hdr)+DATA_BYTES];
                    memcpy(header_plus_data, header_content, sizeof(gsmtap_hdr));
                    memcpy(header_plus_data+sizeof(gsmtap_hdr), outmsg, DATA_BYTES);

                    pmt::pmt_t msg_binary_blob = pmt::make_blob(header_plus_data,DATA_BYTES+sizeof(gsmtap_hdr));
                    pmt::pmt_t msg_out = pmt::cons(pmt::PMT_NIL, msg_binary_blob);

                    message_port_pub(pmt::mp("msgs"), msg_out);
                }
            }

            mVR204Coder.decode(mClass1_c, mTCHU);
            mClass2_c.sliced().copyToSegment(mTCHD, 182);

            // 3.1.2.1
            // copy class 1 bits u[] to d[]
            for (unsigned k = 0; k <= 90; k++) {
              mTCHD[2*k] = mTCHU[k];
              mTCHD[2*k+1] = mTCHU[184-k];
            }

            Parity mTCHParity(0x0b, 3, 50);

            // 3.1.2.1
            // check parity of class 1A
            unsigned sentParity = (~mTCHU.peekField(91, 3)) & 0x07;
            unsigned calcParity = mClass1A_d.parity(mTCHParity) & 0x07;

            bool good = (sentParity == calcParity);

            if (good)
            {
                unsigned char mTCHFrame[33];
                unsigned int  mTCHFrameLength;

                if (d_tch_mode == TCH_FS) // GSM-FR
                {
                    // Undo Um's importance-sorted bit ordering.
                    // See GSM 05.03 3.1 and Tablee 2.
                    VocoderFrame mVFrame;

                    BitVector payload = mVFrame.payload();
                    mTCHD.unmap(GSM::g610BitOrder, 260, payload);
                    mVFrame.pack(mTCHFrame);
                    mTCHFrameLength = 33;
                }
                else if (d_tch_mode == TCH_EFR) // GSM-EFR / AMR 12.2
                {
                    VocoderAMRFrame mVFrameAMR;

                    BitVector payload = mVFrameAMR.payload();
                    BitVector TCHW(260), EFRBits(244);

                    // Undo Um's EFR bit ordering.
                    mTCHD.unmap(GSM::g660BitOrder, 260, TCHW);

                    // Remove repeating bits and CRC to get raw EFR frame (244 bits)
                    for (unsigned k=0; k<71; k++)
                      EFRBits[k] = TCHW[k] & 1;

                    for (unsigned k=73; k<123; k++)
                      EFRBits[k-2] = TCHW[k] & 1;

                    for (unsigned k=125; k<178; k++)
                      EFRBits[k-4] = TCHW[k] & 1;

                    for (unsigned k=180; k<230; k++)
                      EFRBits[k-6] = TCHW[k] & 1;

                    for (unsigned k=232; k<252; k++)
                      EFRBits[k-8] = TCHW[k] & 1;

                    // Map bits as AMR 12.2k
                    EFRBits.map(GSM::g690_12_2_BitOrder, 244, payload);

                    // Put the whole frame (hdr + payload)
                    mVFrameAMR.pack(mTCHFrame);
                    mTCHFrameLength = 32;
                }
                fwrite(mTCHFrame, 1 , mTCHFrameLength, d_speech_file);
            }
        }
    }
  } /* namespace gsm */
} /* namespace gr */

