FreeCalypso > hg > ice1-trau-tester
view ater/tx_func.c @ 52:626180a15857 default tip
ater play-d144: emit E-data frames manually,
osmo_trau_frame_encode() is currently broken for this frame type
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Wed, 25 Sep 2024 06:40:43 +0000 |
parents | db39e8855f3d |
children |
line wrap: on
line source
/* * Here we are going to implement Tx on Ater toward the TRAU. */ #include <stdint.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <osmocom/core/bits.h> #include <osmocom/core/msgb.h> #include <osmocom/core/select.h> #include <osmocom/isdn/i460_mux.h> #include <osmocom/trau/trau_frame.h> #include "globals.h" #include "submux.h" #include "out_frame.h" /* * The following hard-coded frame is based on TS 48.060 section 5.3.1. * 0-based octet numbers in the comments are as in the spec. */ static const ubit_t d144_sync_frame[320] = { 0, 0, 0, 0, 0, 0, 0, 0, /* octet 0 */ 0, 0, 0, 0, 0, 0, 0, 0, /* octet 1 */ 1, 1, 0, 1, 0, 0, 1, 1, /* octet 2 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 3 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 4 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 5 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 6 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 7 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 8 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 9 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 10 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 11 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 12 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 13 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 14 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 15 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 16 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 17 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 18 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 19 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 20 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 21 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 22 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 23 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 24 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 25 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 26 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 27 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 28 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 29 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 30 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 31 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 32 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 33 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 34 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 35 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 36 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 37 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 38 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 39 */ }; /* * The following hard-coded frame is based on TS 48.060 section 5.3.2. * 0-based octet numbers in the comments are as in the spec. */ static const ubit_t d144_idle_edata[320] = { 0, 0, 0, 0, 0, 0, 0, 0, /* octet 0 */ 0, 0, 0, 0, 0, 0, 0, 0, /* octet 1 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 2 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 3 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 4 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 5 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 6 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 7 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 8 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 9 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 10 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 11 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 12 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 13 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 14 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 15 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 16 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 17 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 18 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 19 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 20 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 21 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 22 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 23 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 24 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 25 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 26 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 27 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 28 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 29 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 30 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 31 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 32 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 33 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 34 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 35 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 36 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 37 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 38 */ 1, 1, 1, 1, 1, 1, 1, 1, /* octet 39 */ }; void init_trau_ul_frame(int nr) { struct ater_subslot *at = &subslots[nr]; struct osmo_trau_frame *fr = &at->ul_frame; fr->type = at->is_efr ? OSMO_TRAU16_FT_EFR : OSMO_TRAU16_FT_FR; fr->dir = OSMO_TRAU_DIR_UL; memset(fr->c_bits + 5, 0, 6); memset(fr->c_bits + 15, 1, 6); memset(fr->t_bits, 1, 4); } void init_trau_ul_frame_csd(int nr, bool ir_16k) { struct ater_subslot *at = &subslots[nr]; struct osmo_trau_frame *fr = &at->ul_frame; fr->type = OSMO_TRAU16_FT_DATA; fr->dir = OSMO_TRAU_DIR_UL; fr->c_bits[5] = ir_16k; memset(fr->c_bits + 6, 1, 9); memset(fr->d_bits, 1, 63 * 4); } static void d144_play_frame(ubit_t *out, const uint8_t *filerec) { memset(out, 0, 16); memset(out + 16, 1, 6); out[22] = 0; memset(out + 23, 1, 7); out[30] = (filerec[1] & 2) >> 1; out[31] = filerec[1] & 1; osmo_pbit2ubit(out + 32, filerec + 2, 288); } static void d144_fill_frame(struct ater_subslot *at, ubit_t *out) { if (at->play_buffer) { d144_play_frame(out, at->play_buffer + at->play_buf_ptr * 38); at->play_buf_ptr++; if (at->play_buf_ptr < at->play_buf_total) return; free(at->play_buffer); at->play_buffer = NULL; printf("file play finished\n"); return; } memcpy(out, at->d144_edata ? d144_idle_edata : d144_sync_frame, 320); } static void handle_d144(int nr) { struct ater_subslot *at = &subslots[nr]; struct msgb *msg; msg = msgb_alloc_c(g_ctx, 320, "TRAU-UL-frame"); if (!msg) return; d144_fill_frame(at, msg->tail); msgb_put(msg, 320); osmo_i460_mux_enqueue(at->schan, msg); } static void handle_play(struct ater_subslot *at) { if (at->play_wait_align) { if (at->mfrm_count) return; at->play_wait_align = false; } trau_frame_from_record(at->play_buffer + at->play_buf_ptr * 34, at->is_efr, &at->ul_frame); at->play_buf_ptr++; if (at->play_buf_ptr < at->play_buf_total) return; free(at->play_buffer); at->play_buffer = NULL; printf("file play finished\n"); } static void tx_service_subslot(int nr) { struct ater_subslot *at = &subslots[nr]; struct osmo_trau_frame *fr = &at->ul_frame; struct msgb *msg; int len; if (!at->is_active) return; if (at->is_data_144) { handle_d144(nr); return; } if (at->play_buffer) handle_play(at); if (!at->is_data) { at->mfrm_count++; if (at->mfrm_count >= 24) { at->mfrm_count = 0; fr->c_bits[14] = 1; } else { fr->c_bits[14] = 0; } } msg = msgb_alloc_c(g_ctx, 640, "TRAU-UL-frame"); if (!msg) return; len = osmo_trau_frame_encode(msg->tail, msgb_tailroom(msg), fr); if (len <= 0) { msgb_free(msg); return; } /* * A very ugly/hacky way of setting C5 for HR data, * working around libosmotrau API that is not designed * for such hacking. */ if (at->is_data && at->is_hr_data) msg->tail[21] = 1; msgb_put(msg, len); osmo_i460_mux_enqueue(at->schan, msg); } void transmit_e1_ts(void) { uint8_t buf[160]; int nr; for (nr = 0; nr < ATER_SUBSLOTS; nr++) tx_service_subslot(nr); osmo_i460_mux_out(&i460_ts, buf, 160); write(ts_fd, buf, 160); }