blob: e5a889dcf71851eaaab83419ed5a5704f33c471b [file] [log] [blame]
Pau Espin Pedrol15fa64b2019-07-01 20:41:55 +02001/*
2 * Copyright (C) 2019 sysmocom - s.f.m.c. GmbH
3 * All Rights Reserved
4 *
5 * SPDX-License-Identifier: AGPL-3.0+
6 *
7 * Author: Pau Espin Pedrol <pespin@sysmocom.de>
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
18 *
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * See the COPYING file in the main directory for details.
22 */
23
24#include "proto_trxd.h"
25
26#include <osmocom/core/bits.h>
27
28static void trxd_fill_common(struct trxd_hdr_common *common, const struct trx_ul_burst_ind *bi, uint8_t version)
29{
Vadim Yanitskiy6fa906c2019-07-20 14:17:45 +070030 common->version = version & 0b1111;
Pau Espin Pedrol15fa64b2019-07-01 20:41:55 +020031 common->reserved = 0;
32 common->tn = bi->tn;
33 osmo_store32be(bi->fn, &common->fn);
34}
35
36static void trxd_fill_v0_specific(struct trxd_hdr_v0_specific *v0, const struct trx_ul_burst_ind *bi)
37{
38 int toa_int;
39
40 /* in 1/256 symbols, round to closest integer */
41 toa_int = (int) (bi->toa * 256.0 + 0.5);
42 v0->rssi = bi->rssi;
43 osmo_store16be(toa_int, &v0->toa);
44}
45
Pau Espin Pedrolcf6113b2019-07-01 20:42:53 +020046static void trxd_fill_v1_specific(struct trxd_hdr_v1_specific *v1, const struct trx_ul_burst_ind *bi)
47{
48 int16_t ci_int_cB;
49
50 /* deciBels->centiBels, round to closest integer */
51 ci_int_cB = (int16_t)((bi->ci * 10) + 0.5);
52
53 v1->idle = !!bi->idle;
54 v1->modulation = (bi->modulation == MODULATION_GMSK) ?
55 TRXD_MODULATION_GMSK(bi->tss) :
56 TRXD_MODULATION_8PSK(bi->tss);
57 v1->tsc = bi->tsc;
58 osmo_store16be(ci_int_cB, &v1->ci);
59}
60
Pau Espin Pedrol15fa64b2019-07-01 20:41:55 +020061static void trxd_fill_burst_normalized255(uint8_t* soft_bits, const struct trx_ul_burst_ind *bi)
62{
63 unsigned i;
64 for (i = 0; i < bi->nbits; i++)
Pau Espin Pedrolb536ab92020-06-19 18:31:02 +020065 soft_bits[i] = (uint8_t) round(bi->rx_burst[i] * 255.0);
Pau Espin Pedrol15fa64b2019-07-01 20:41:55 +020066}
67
68bool trxd_send_burst_ind_v0(size_t chan, int fd, const struct trx_ul_burst_ind *bi) {
69 int rc;
70
71 /* v0 doesn't support idle frames, they are simply dropped, not sent */
Vadim Yanitskiy54bde5a2020-07-26 02:53:11 +070072 if (bi->idle)
Pau Espin Pedrol15fa64b2019-07-01 20:41:55 +020073 return true;
74
Martin Hauke066fd042019-10-13 19:08:00 +020075 /* +2: Historically (OpenBTS times), two extra non-used bytes are sent appended to each burst */
Pau Espin Pedrol15fa64b2019-07-01 20:41:55 +020076 char buf[sizeof(struct trxd_hdr_v0) + bi->nbits + 2];
77 struct trxd_hdr_v0* pkt = (struct trxd_hdr_v0*)buf;
78
79 trxd_fill_common(&pkt->common, bi, 0);
80 trxd_fill_v0_specific(&pkt->v0, bi);
81 trxd_fill_burst_normalized255(&pkt->soft_bits[0], bi);
82
83 /* +1: Historical reason. There's an uninitizalied byte in there: pkt->soft_bits[bi->nbits] */
84 pkt->soft_bits[bi->nbits + 1] = '\0';
85
86 rc = write(fd, buf, sizeof(struct trxd_hdr_v0) + bi->nbits + 2);
87 if (rc <= 0) {
88 CLOGCHAN(chan, DMAIN, LOGL_NOTICE, "mDataSockets write(%d) failed: %d\n", fd, rc);
89 return false;
90 }
91 return true;
92}
Pau Espin Pedrolcf6113b2019-07-01 20:42:53 +020093
94bool trxd_send_burst_ind_v1(size_t chan, int fd, const struct trx_ul_burst_ind *bi) {
95 int rc;
96 size_t buf_len;
97
98 buf_len = sizeof(struct trxd_hdr_v1);
99 if (!bi->idle)
100 buf_len += bi->nbits;
101 char buf[buf_len];
102
103 struct trxd_hdr_v1* pkt = (struct trxd_hdr_v1*)buf;
104 trxd_fill_common(&pkt->common, bi, 1);
105 trxd_fill_v0_specific(&pkt->v0, bi);
106 trxd_fill_v1_specific(&pkt->v1, bi);
107
108 if (!bi->idle)
109 trxd_fill_burst_normalized255(&pkt->soft_bits[0], bi);
110
111 rc = write(fd, buf, buf_len);
112 if (rc <= 0) {
113 CLOGCHAN(chan, DMAIN, LOGL_NOTICE, "mDataSockets write(%d) failed: %d\n", fd, rc);
114 return false;
115 }
116 return true;
117}