my patch for decode using burst_id

This is merely a historical archive of years 2008-2021, before the migration to mailman3.

A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/baseband-devel@lists.osmocom.org/.

bob wisebob avwiseav at gmail.com
Mon Jun 18 08:32:52 UTC 2012


Hi,List
 I found BB is a great project,and I want to study it. In my test network
without encryption, I test the burst_id with dsp patch to capture the SMS,
and also ,I patch the ccch_scan to capture the voice,but I met a few
difficulty, but the amr voice file seems not good, I found it hard to find
the error, anyone can help me? Thanks!
the patch is following:

static struct {
    int            has_si1;
    int            has_si3;
    int            ccch_mode;
    int            neci;
    int            sys_count;

    enum dch_state_t    dch_state;
    uint8_t            dch_nr;
    int            dch_badcnt;
    int            dch_ciph;

    FILE *            fh;

    sbit_t            bursts_dl[116 * 4];
    sbit_t            bursts_ul[116 * 4];
    sbit_t            bursts_ccch[4][116*4];
    sbit_t            mI[8][114];

    struct gsm_sysinfo_freq    cell_arfcns[1024];

    uint8_t            kc[8];
} app_state;

static char *
void layer3_rx_burst(struct osmocom_ms *ms, struct msgb *msg)
{
    struct l1ctl_burst_ind *bi;
    int16_t rx_dbm;
    uint16_t arfcn;
    int ul,do_rel=0;

    /* Header handling */
    bi = (struct l1ctl_burst_ind *) msg->l1h;

    arfcn = ntohs(bi->band_arfcn);
    rx_dbm = rxlev2dbm(bi->rx_level);
    ul = !!(arfcn & ARFCN_UPLINK);

    if (app_state.dch_state == DCH_NONE)
        local_ccch_burst_decode(bi,ms);
    /* Check for channel start */
    if (app_state.dch_state == DCH_WAIT_EST) {
        if (bi->chan_nr == app_state.dch_nr) {
            if (bi->snr > 64) {
                /* Change state */
                app_state.dch_state = DCH_ACTIVE;
                app_state.dch_badcnt = 0;

                /* Open output */
                //app_state.fh = fopen(gen_filename(ms, bi), "wb");
            } else {
                /* Abandon ? */
                do_rel = (app_state.dch_badcnt++) >= 4;
            }
        }
    }

    /* Check for channel end */
    if (app_state.dch_state == DCH_ACTIVE) {
        if (!ul) {
            /* Bad burst counting */
            if (bi->snr < 64)
                {
                    app_state.dch_badcnt++;
                    printf("sdcch app_state.dch_badcnt++\n");
                }
            else if (app_state.dch_badcnt >= 2)
                app_state.dch_badcnt -= 2;
            else
                app_state.dch_badcnt = 0;

            /* Release condition */
            do_rel = app_state.dch_badcnt >= 6;
        }
    }

    // when in TCH mode, we only measure the SACCH to kown the link quanlity
    if (app_state.dch_state == DCH_TCH) {
        //printf("app_state.dch_state == DCH_TCH\n");
        if (!ul && (bi->flags & BI_FLG_SACCH)) {
            //printf("TCH SACCH\n");
            /* Bad burst counting */
            if (bi->snr < 40)
                {
                    app_state.dch_badcnt++;
                    printf("sacch app_state.dch_badcnt++\n");
                }
            else if (app_state.dch_badcnt >= 2)
                app_state.dch_badcnt -= 2;
            else
                app_state.dch_badcnt = 0;

            /* Release condition */
            do_rel = app_state.dch_badcnt >= 6;
        }
    }

    /* Release ? */
    if (do_rel) {
        printf("The Delicate Channel is released because of bad SNR!\n");
        /* L1 release */
        l1ctl_tx_dm_rel_req(ms);
        l1ctl_tx_fbsb_req(ms, ms->test_arfcn,
                L1CTL_FBSB_F_FB01SB, 100, 0,
                app_state.ccch_mode);

        /* Change state */
        app_state.dch_state = DCH_WAIT_REL;
        app_state.dch_badcnt = 0;
        app_state.dch_ciph = 0;

        /* Close output */
        if (app_state.fh) {
            fclose(app_state.fh);
            app_state.fh = NULL;
        }
    }

    /* Save the burst */
    if (app_state.dch_state == DCH_ACTIVE || app_state.dch_state == DCH_TCH)
        //fwrite(bi, sizeof(*bi), 1, app_state.fh);

    /* Try local decoding */
    if (!ul && (app_state.dch_state == DCH_ACTIVE || app_state.dch_state ==
DCH_TCH))
        local_burst_decode(ms,bi);
}

static void
local_burst_decode(struct osmocom_ms *ms,struct l1ctl_burst_ind *bi)
{
    int16_t rx_dbm;
    uint16_t arfcn;
    uint32_t fn;
    uint8_t cbits, tn, lch_idx;
    int ul, bid, i, d_tch_mode;
    sbit_t *bursts;
    ubit_t bt[116];

    /* Get params (Only for SDCCH and SACCH/{4,8,F,H}) */
    arfcn  = ntohs(bi->band_arfcn);
    rx_dbm = rxlev2dbm(bi->rx_level);

    fn     = ntohl(bi->frame_nr);
    ul     = !!(arfcn & ARFCN_UPLINK);
    bursts = ul ? app_state.bursts_ul : app_state.bursts_dl;

    cbits  = bi->chan_nr >> 3;
    tn     = bi->chan_nr & 7;

    bid    = -1;

    if (cbits == 0x01) {            /* TCH/F */
        lch_idx = 0;
        if (bi->flags & BI_FLG_SACCH) {
            uint32_t fn_report;
            fn_report = (fn - (tn * 13) + 104) % 104;
            bid = (fn_report - 12) / 26;
            printf(" SACCH fn = %d fn_report = %d\n",fn,fn_report);
        }else{
            //printf(" TCH/F \n");
            process_tch_f(ms,bi);
        }
    } else if ((cbits & 0x1e) == 0x02) {    /* TCH/H */
        lch_idx = cbits & 1;
        if (bi->flags & BI_FLG_SACCH) {
            uint32_t fn_report;
            uint8_t tn_report = (tn & ~1) | lch_idx;
            fn_report = (fn - (tn_report * 13) + 104) % 104;
            bid = (fn_report - 12) / 26;
        }
    } else if ((cbits & 0x1c) == 0x04) {    /* SDCCH/4 */
        lch_idx = cbits & 3;
        bid = bi->flags & 3;
        printf(" SDCCH/4\n");
    } else if ((cbits & 0x18) == 0x08) {    /* SDCCH/8 */
        lch_idx = cbits & 7;
        bid = bi->flags & 3;
        //printf(" SDCCH/8\n");
    }

    if (bid == -1)
        return;

    /* Clear if new set */
    if (bid == 0)
        memset(bursts, 0x00, 116 * 4);

    /* Unpack (ignore hu/hl) */
    osmo_pbit2ubit_ext(bt,  0, bi->bits,  0, 57, 0);
    osmo_pbit2ubit_ext(bt, 59, bi->bits, 57, 57, 0);
    bt[57] = bt[58] = 1;

    /* A5/x */
    if (app_state.dch_ciph) {
        ubit_t ks_dl[114], ks_ul[114], *ks = ul ? ks_ul : ks_dl;
        osmo_a5(app_state.dch_ciph, app_state.kc, fn, ks_dl, ks_ul);
        for (i= 0; i< 57; i++)  bt[i] ^= ks[i];
        for (i=59; i<116; i++)  bt[i] ^= ks[i-2];
    }

    /* Convert to softbits */
    for (i=0; i<116; i++)
        bursts[(116*bid)+i] = bt[i] ? - (bi->snr >> 1) : (bi->snr >> 1);

    /* If last, decode */
    if (bid == 3)
    {
        uint8_t l2[23];
        int rv,i;
        struct  gsm48_ass_cmd *ia;
        uint8_t ch_type, ch_subch, ch_ts;
        uint8_t chan_req_val, chan_req_mask, ra;

        rv = xcch_decode(l2, bursts);

        if((l2[0] == 0x03) && (l2[4] == 0x2e))
        {
            ia =(struct  gsm48_ass_cmd *)&l2[5];

            rsl_dec_chan_nr(ia->chan_desc.chan_nr, &ch_type, &ch_subch,
&ch_ts);
            //l1ctl_tx_reset_req(ms, L1CTL_RES_T_SCHED);
            printf("Jump to TCH Channel\n");

            d_tch_mode = GSM48_CMODE_SPEECH_EFR;
            /* open speech file and configure d_tch_decoders */
            switch (d_tch_mode) {

            case GSM48_CMODE_SPEECH_V1:
                d_speech_file = fopen( "speech.au.gsm", "wb" );
                break;

            case GSM48_CMODE_SPEECH_EFR:
                d_speech_file = fopen( gen_filename(ms,bi), "wb" );
                fwrite(amr_nb_magic, 1, 6, d_speech_file); /* Write header
*/
                break;

            default:
                d_speech_file = NULL;

  }
            app_state.dch_state = DCH_TCH;

            if (!ia->chan_desc.h0.h) {
                /* Non-hopping */
                uint16_t arfcn;

                arfcn = ia->chan_desc.h0.arfcn_low |
(ia->chan_desc.h0.arfcn_high << 8);

                LOGP(DRR, LOGL_NOTICE, "ASS CMD(chan_nr=0x%02x, "
                    "ARFCN=%u, TS=%u, SS=%u, TSC=%u) ",
                    ia->chan_desc.chan_nr, arfcn, ch_ts, ch_subch,
                    ia->chan_desc.h0.tsc);

                /* request L1 to go to dedicated mode on assigned channel */
                rv = l1ctl_tx_dm_est_req_h0(ms,
                    arfcn, ia->chan_desc.chan_nr, ia->chan_desc.h0.tsc,
                    GSM48_CMODE_SPEECH_EFR, 0);
            }
        #ifdef TCH_HOPPING
             else {
                /* Hopping is not support now! */
                uint8_t maio, hsn, ma_len;
                uint16_t ma[64], arfcn;
                int i, j, k;

                hsn = ia->chan_desc.h1.hsn;
                maio = ia->chan_desc.h1.maio_low |
(ia->chan_desc.h1.maio_high << 2);

                LOGP(DRR, LOGL_NOTICE, "ASS CMD( chan_nr=0x%02x, "
                    "HSN=%u, MAIO=%u, TS=%u, SS=%u, TSC=%u) ",
                    ia->chan_desc.chan_nr, hsn, maio, ch_ts, ch_subch,
                    ia->chan_desc.h1.tsc);

                /* decode mobile allocation */
                ma_len = 0;
                for (i=1, j=0; i<=1024; i++) {
                    arfcn = i & 1023;
                    if (app_state.cell_arfcns[arfcn].mask & 0x01) {
                        k = ia->mob_alloc_len - (j>>3) - 1;
                        if (ia->mob_alloc[k] & (1 << (j&7))) {
                            ma[ma_len++] = arfcn;
                        }
                        j++;
                    }
                }

                /* request L1 to go to dedicated mode on assigned channel */
                rv = l1ctl_tx_dm_est_req_h1(ms,
                    maio, hsn, ma, ma_len,
                    ia->chan_desc.chan_nr, ia->chan_desc.h1.tsc,
                    GSM48_CMODE_SPEECH_EFR, 0);
            }
        #endif
        }

        if (rv == 0)
        {
            uint8_t chan_type, chan_ts, chan_ss;
            uint8_t gsmtap_chan_type;

            /* Send to GSMTAP */
            rsl_dec_chan_nr(bi->chan_nr, &chan_type, &chan_ss, &chan_ts);
            gsmtap_chan_type = chantype_rsl2gsmtap(
                chan_type,
                bi->flags & BI_FLG_SACCH ? 0x40 : 0x00
            );
            gsmtap_send(gsmtap_inst,
                arfcn, chan_ts, gsmtap_chan_type, chan_ss,
                ntohl(bi->frame_nr), bi->rx_level, bi->snr,
                l2, sizeof(l2)
            );

            /* Crude CIPH.MOD.COMMAND detect */
            if ((l2[3] == 0x06) && (l2[4] == 0x35) && (l2[5] & 1))
                app_state.dch_ciph = 1 + ((l2[5] >> 1) & 7);
        }
    }
}

void tch_deinterleave(ubit_t *mC, int blockOffset)
{
    int k;
    for (k = 0; k < 456; k++) {
        int B = ( k + blockOffset ) % 8;
        int j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
        mC[k] = app_state.mI[B][j];
        app_state.mI[B][j] = 0;
        //OBJDCOUT("deinterleave k="<<k<<" B="<<B<<" j="<<j);
    }
}

void tch_unmap(const uint16_t *map, size_t mapSize, ubit_t * dest, ubit_t *
soure)
{
    unsigned int i;
    for(i=0; i<mapSize; i++)
    {
        dest[map[i]] = soure[i];
    }
}

void tch_map(const uint16_t *map, size_t mapSize, ubit_t * dest, ubit_t *
soure)
{
    unsigned int i;
    for(i=0; i<mapSize; i++)
    {
        dest[i] = soure[map[i]];
    }
}

void fillField(ubit_t *mStart, size_t writeIndex, uint64_t value, unsigned
length)
{
    char *dpBase = mStart + writeIndex;
    char *dp = dpBase + length - 1;

    while (dp>=dpBase) {
        *dp-- = value & 0x01;
        value >>= 1;
    }
}

uint64_t count_tch = 0;

static void process_tch_f(struct osmocom_ms *ms,struct l1ctl_burst_ind *bi)
{
    int16_t rx_dbm;
    uint16_t arfcn;
    uint32_t fn,B;
    uint8_t cbits, tn, lch_idx;
    int ul, bid, i, k, length;
    sbit_t *bursts, mC[456];
    ubit_t
bt[114],convu[189],convd[189],tch_raw[260],TCHW[260],EFRBits[244],EFRAMR[8
+ 244];

    pbit_t voice[33];
    /* Get params (Only for SDCCH and SACCH/{4,8,F,H}) */
    arfcn  = ntohs(bi->band_arfcn);
    rx_dbm = rxlev2dbm(bi->rx_level);

    fn     = ntohl(bi->frame_nr);
    ul     = !!(arfcn & ARFCN_UPLINK);

    cbits  = bi->chan_nr >> 3;
    tn     = bi->chan_nr & 7;

    B  = -1;

    B = count_tch % 8;

    if (B == -1)
        return;

    /* Clear if new set */
    if (B == 0){
        for(i=0; i<4; i++){
            memset(app_state.mI[i], 0x00, 114);
        }
    }else if(B == 4){
        for(i=4; i<8; i++){
            memset(app_state.mI[i], 0x00, 114);
        }
    }

    /* Unpack (ignore hu/hl) */
    osmo_pbit2ubit_ext(bt,  0, bi->bits,  0, 57, 0);
    osmo_pbit2ubit_ext(bt, 57, bi->bits, 57, 57, 0);

    /* Convert to softbits */
    for (i=0; i<114; i++)
        app_state.mI[B][i] = bt[i] ? - (bi->snr >> 1) : (bi->snr >> 1);

    count_tch++;
    // Deinterleave according to the diagonal "phase" of B.
    // See GSM 05.03 3.1.3.
    // Deinterleaves i[] to c[]
    if((B % 4 ==3)&&(count_tch >= 7)){
        if(B == 3)
        {
            tch_deinterleave(mC, 4);
        }else{
            tch_deinterleave(mC, 0);
        }

        for (k = 0; k < 78; k++) {
            tch_raw[182 + k] = mC[378 +k];
        }

        osmo_conv_decode(&conv_tch_afs_12_2, mC, convu);

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

        memcpy(tch_raw,convd,182);    // the last 78 bit has been stored!

        //now only process EFR or AMR 12_2, fix me!
        tch_unmap(gsm660_bitorder, 260, TCHW, tch_raw);

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

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

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

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

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

        // Map bits as AMR 12.2k
        tch_map(gsm690_12_2_bitorder, 244, EFRAMR + 8,EFRBits);

        // Put the whole frame (hdr + payload)
        //mVFrameAMR.pack(mPrevGoodFrame);
        //mPrevGoodFrameLength = 32;
        fillField(EFRAMR, 0, 0x3c, 8);
        voice[32] = 0;
        length = osmo_ubit2pbit(voice, EFRAMR, 8 + 244);
        fwrite(voice, 1, 32, d_speech_file);
    }

}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.osmocom.org/pipermail/baseband-devel/attachments/20120618/aa14166f/attachment.htm>


More information about the baseband-devel mailing list